Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make BackgroundWorker ProgressChanged events execute in sequence?

Consider the following code:

private static BackgroundWorker bg = new BackgroundWorker();

static void Main(string[] args) {
  bg.DoWork += bg_DoWork;
  bg.ProgressChanged += bg_ProgressChanged;
  bg.WorkerReportsProgress = true;
  bg.RunWorkerAsync();

  Thread.Sleep(10000);
}

static void bg_ProgressChanged(object sender, ProgressChangedEventArgs e) {
  Console.WriteLine(e.ProgressPercentage);
  Thread.Sleep(100);
  Console.WriteLine(e.ProgressPercentage);
}

static void bg_DoWork(object sender, DoWorkEventArgs e) {
  for (int i = 0; i < 10; i++) {
    bg.ReportProgress(i);
  }
}

When run I get the following output:

0 1 1 2 0 3 2 3 5 4 4 6 5 7 7 8 6 9 8 9

I understand that the issue is a race condition between the threads that BackgroundWorker starts for each call to ReportProgress.

How can I make sure that the whole body of each bg_ProgressChanged gets executed in the order I have called them? That is I would like to get

0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9

as a result.

like image 807
Andris Avatar asked Nov 07 '11 16:11

Andris


1 Answers

BackgroundWorker raises ProgressChanged events on the current SynchronizationContext of the thread that called RunWorkerAsync().

The default SynchronizationContext runs callbacks on the ThreadPool without any synchronization.

If you use BackgroundWorker in a UI application (WPF or WinForms), it will use that UI platform's SynchronizationContext, which will execute callbacks in order.

like image 75
SLaks Avatar answered Nov 20 '22 21:11

SLaks