1

I have a Background worker in the ViewModel. When ever the Command for a button is executed I want to start the process in a new thread. Here is my sample Code

private void ShowValidations(object obj)
        {
            progress = "Please Wait....";
            var worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += worker_DoWork;
            worker.ProgressChanged += worker_ProgressChanged;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}

And in the Do work method I have

  private void worker_DoWork(object sender, DoWorkEventArgs e)
            {

                var worker = sender as BackgroundWorker;

                DoValidation();
                for(int i=0;i<100;i++)
                {
                    worker.ReportProgress(i); //Not sure here what should be written in the Background Worker Report progress event.
                }
            }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            ViewSource.Source = _validationResults;
            ViewSource.View.Refresh();
            progress = "Validations Complete";
            Isindeterminate = false;
            //prvalue = 99;
        }

DoValidation is method the fetches results for an other class just like a three tier architecture.

private void DoValidation()
        {
            try
            {

                if (!string.IsNullOrEmpty(_selectedEntity))
                {

                    var jobEngine = new JobEngine();
                    var jobId = JobEntities[0].JobId;                   
                    jobEngine.ProcessValidation(_selectedEntity, jobId); //Get results from other class.
                    _validationResults = _validations.ValidationSummary(_selectedEntity, jobId);  //_validationResults is an Observable Collection. 

                }

                else
                {
                    MessageBox.Show("Please select an Entity to validate");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "Sorry we are having problems with " + _selectedEntity);
            }
        }

How do I update the progress bar on the UI based on the work that is done. What should be in the ProgressChanged Event of the background worker.. Here is my View code.

  <ProgressBar HorizontalAlignment="Left" Minimum="1" Maximum="99" Height="20" Margin="424,24,0,0" Grid.Row="1" Value="{Binding prvalue,Mode=OneWay}" VerticalAlignment="Top" Width="194"/>
        <Label x:Name="LblprogressLabel" FontSize="14" Content="{Binding prvalue,Mode=OneWay}" HorizontalAlignment="Center" Margin="507,18,339,23" Grid.Row="1" Width="26"/>
        <Label Content="{Binding progress,Mode=OneWay}" FontSize="16" FontWeight="Bold" HorizontalAlignment="Left" Margin="623,20,0,0" Grid.Row="1" VerticalAlignment="Top" Width="227" Height="34"/>

Please dont worry about datacontext everything is fine. I cant write the entire code of each class as it is so huge. Please Help!!!!

nikhil
  • 1,578
  • 3
  • 23
  • 52
  • 1
    There are lots of Q&As on SO already that address the basic question of how to handle the `ProgressChanged` event, and how to update a `ProgressBar` object. Have you looked at any of them yet? Have you tried to write your handler yet? What did you actually try so far? Please see https://stackoverflow.com/help/mcve and especially https://stackoverflow.com/help/how-to-ask – Peter Duniho Jan 05 '15 at 23:44
  • Yes I did. But most of them suggest doing like a for loop and putting in the code I want to do work there. But the problem is If I do so the DoValidations method is executing that many times. Just Like this MSDN link http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx I also tried using the curve ball approach by using the dispatcher tick event but no luck. http://stackoverflow.com/questions/9602567/how-to-update-ui-from-another-thread-running-in-another-class – nikhil Jan 05 '15 at 23:50
  • 1
    If all of the work is contained in `DoValidations()`, then you need for `DoValidations()` to provide the progress update mechanism. You can't just call the method and then _later_ do the progress updates. That's not useful to the user at all. Your first step is to determine what your definition of a single step of progress is; then you can figure out where and how to signal that. "Progress" won't make any sense until you've somehow created divisions of your work that would be represented on the `ProgressBar`. – Peter Duniho Jan 06 '15 at 00:01
  • DoValidation is nothing but a shell reading data from sql table using datareader and performing inserts into another table.. I dont want the overhead of calling sql twice to see the total count of rows from which I am reading and compare it with number of rows iam inserting. I am fine with considering the logic as a whole batch. If there is way to communicate with my UI in WPF while my data reader is going row by row.It would be a perfect match for me.But I am unable to figure out a proper way to communicat with UI while my sql commands are still executing. – nikhil Jan 06 '15 at 00:30
  • Note:You can say one row read and one rows inserted as one unit of progress – nikhil Jan 06 '15 at 00:32
  • 1
    You certainly can "communicate with your UI" -- one mechanism would be to encapsulate the reader logic in a class that itself has a progress-reporting mechanism (e.g. an event like `BackgroundWorker`'s `ProgressChanged`). But unless you know what the total # of rows is, there's no meaningful way to report that to the user. Maybe you just want to set the [`ProgressBar.IsIndeterminate`](http://msdn.microsoft.com/en-us/library/system.windows.controls.progressbar.isindeterminate(v=vs.110).aspx) property to `true` and not even handle the `ProgressChanged` event? – Peter Duniho Jan 06 '15 at 01:08

0 Answers0