Sam Rabeeh
Sam Rabeeh

Reputation: 129

WPF BackGroundWorker ProgressChanged not updating textblock

I have the method below that seems to behaving strangely. The ProgressChanged and RunWorkerCompleted seem to be updating themselves at the same time. If I comment out the RunWorkerCompleted code which updates the textblock I see the ProgressChanged taking effect after the data is transferred. What am I doing wrong here? I obviously want the textblock to show I'm getting data, then change when I have finished getting the data.

public void GetAppointmentsBackground()
{
   System.Windows.Threading.Dispatcher webServiceDispatcher = this.Dispatcher;
   worker = new BackgroundWorker();
   worker.WorkerReportsProgress = true;
   worker.DoWork += delegate(object sender, DoWorkEventArgs args)
   {
     GetAppointmentsForDayDelegate getAppt = new GetAppointmentsForDayDelegate(GetAppointmentsForDay);
     webServiceDispatcher.BeginInvoke(getAppt);
     (sender as BackgroundWorker).ReportProgress(25);
   };

   worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
   {
     txtMessages.Text = "Contacting Server";
   };

   worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
   {
     txtMessages.Text = "Completed Successfully";
   };

   worker.RunWorkerAsync();
}

Upvotes: 1

Views: 1395

Answers (2)

Alexey Khoroshikh
Alexey Khoroshikh

Reputation: 11

In fact, the thing is that another model is used for System.Windows.Controls (differs from Windows.Forms.Control descendants). I used something like:

public delegate void NoArgs();

//...

txtBlock.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, 
    new NoArgs(UpdateTextBlock));

//...

void UpdateTextBlock()
{
    txtBlock.Text = "Contacting Server";
}

Read the manual about Dispatcher and DispatcherObject for the purpose.

Upvotes: 1

t0mm13b
t0mm13b

Reputation: 34592

I would suggest you wrap this up in a try{...}catch block... and a using clause, as shown below

public void GetAppointmentsBackground()
{
   System.Windows.Threading.Dispatcher webServiceDispatcher = this.Dispatcher;
   try
   {
     using (BackgroundWorker worker = new BackgroundWorker())
     {
       worker.WorkerReportsProgress = true;
       worker.DoWork += delegate(object sender, DoWorkEventArgs args)
       {
          GetAppointmentsForDayDelegate getAppt = new GetAppointmentsForDayDelegate(GetAppointmentsForDay);
          webServiceDispatcher.BeginInvoke(getAppt);
          (sender as BackgroundWorker).ReportProgress(25);
       };

       worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
       {
          txtMessages.Text = "Contacting Server";
       };

       worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
       {
          if (txtMessages.InvokeRequired)
          {
            txtMessages.BeginInvoke(new MethodInvoker(delegate()
            {
               txtMessages.Text = "Completed Successfully";
            }));
          }
          else
          {
             txtMessages.Text = "Completed Successfully";
          }
       };

       worker.RunWorkerAsync();
     }
   }
   catch(Exception eX)
   {
      /* CHECK HERE TO SEE IF AN EXCEPTION IS THROWN */
   }
}

If there is no exception thrown, perhaps using an BeginInvoke method of the txtMessages class as shown above in the RunWorkerCompleted event handler, as there may be a cross-threading error when trying to update the txtMessages itself from the backgroundworker class.

Upvotes: 0

Related Questions