title: Using events and BackgroundWorker to update UI causing race conditions
body: <p>I have two classes, <code>Apple</code> and <code>Dog</code>.  Both of these classes have a method called upon startup, <code>DoLotsOfWork()</code> which publish an event <code>ProgressChanged</code>.</p>
  
  <pre><code>public class Apple
  {
      //For progress bars
      public event EventHandler&lt;ProgressChangedEventArgs&gt; ProgressChanged;
      private void OnProgressChanged(double progress)
      {
          if(ProgressChanged != null)
              ProgressChanged(this, new ProgressChangedEventArgs((int)(progress * 100), null));
      }
  
      //Takes a long time to run
      public void DoLotsOfWork()
      {
          for(lots of things)
          {
              ...
              OnProgressChanged(percentage);
          }
      }
  }
  //Dog is similar
  </code></pre>
  
  <p>To keep the UI from locking up, I have these run using a <code>BackgroundWorker</code>.  I have <code>Apple.ProgressChanged</code> and <code>Dog.ProgressChanged</code> call <code>BackgroundWorker.ReportProgress</code> <em>(which calls the <code>BackgroundWorker.ProgressChanged</code> event)</em> to update a label and a progress bar, so the user knows what's going on.</p>
  
  <pre><code>public class MainForm : Form
  {
      private Apple _apple;
      private Dog _dog;
      private bool _isAppleCompleted;
  
      ...
  
      //Set the ProgressChanged callbacks and start the BackgroundWorker
      private void MainForm_Load(object sender, EventArgs e)
      {
          _apple.ProgressChanged += (a, args) =&gt; backgroundWorker1.ReportProgress(args.ProgressPercentage);
          _dog.ProgressChanged += (a, args) =&gt; backgroundWorker1.ReportProgress(args.ProgressPercentage);
          backgroundWorker1.RunWorkerAsync();
      }
  
      //Invoke the UI thread to set the status/progress
      private void SetStatus(string status)
      {
          lblStatus.Invoke((Action)(() =&gt; lblStatus.Text = status));
      }
      private void SetProgress(int progress)
      {
          progressBar.Invoke((Action)(() =&gt; progressBar.Value = progress));
      }
  
      private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
      {
          _isAppleCompleted = false;
          SetStatus("Apple (Step 1/2)");
          _apple.DoLotsOfWork();
  
          //Thread.Sleep(1); //This *sometimes* fixes the problem!?
  
          _isAppleCompleted = true;
          SetStatus("Dog (Step 2/2)");
          _dog.DoLotsOfWork();
      }
  
      private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
          //_apple.DoLotsOfWork should cause the progress bar to go from 0 to 50
          //_dog.DoLotsOfWork should cause the progress bar to go from 50 to 100
          int progress = (_isAppleCompleted ? 50 : 0) + e.ProgressPercentage/2;
          SetProgress(progress);
      }
  
      private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
          //stuff
      }
  }
  </code></pre>
  
  <p><strong>What I expect to happen:</strong> The text <em>"Apple (Step 1/2)"</em> as the progress bar moves from 0% to 50%.  Then the phrase "Dog (Step 2/2)" is displayed as the progress bar moves from 50% to 100%.</p>
  
  <p><strong>What actually happens:</strong> Only the text "Dog (Step 2/2)" is ever displayed.  The progress bar goes from 0% to 100%, then goes back to 50% and moves up to 100%.</p>
  
  <hr>
  
  <p>Since I <em>thought</em> events handlers are run on the same thread as the event-caller; and I <em>thought</em> <code>Control.Invoke()</code> blocks until the <code>Action</code> is completed, I don't see how there could be any race conditions, since everything is essentially happening synchronously.  <strong>Does anyone have any idea why this would be happening, and how to fix it?</strong></p>
  
  <p>And yes, I checked that <code>0 &lt;= e.ProgressPercentage &lt;= 100</code>, and <code>progressBar.Maximum = 100</code>.</p>