Jun 25

Multithreading: the BackgroundWorker class

Posted in C# Multithreading      Comments Off on Multithreading: the BackgroundWorker class

In the last posts of the series, we’ve been looking at many important features related to GUIs and multithreading. Today, we’re going to wrap up this topic with the BackgroundWorker class. The previous posts are really targeted at library developers.

The truth is that having to implement the EAP pattern  to have asynchronous behavior is simply too much work. Interact with the SynchronizationContext object to have asynchronous behavior is really too cumbersome and involves too much boilerplate code.

Wouldn’t it be good if we had a reusable class where we’d simply need to write the code for the asynchronous operation and that would be able to let us know when things are done? The good news is that there’s already a component you can use for that: the BackgroundWorker class.

The BackgroundWorker class can be seen as a helper class which encapsulates all that boilerplate code we’ve seen in previous posts. Here’s the public API of this class:

public class BackgroundWorker : Component {
  public event DoWorkEventHandler DoWork;
  public event ProgressChangedEventHandler ProgressChanged;
  public event RunWorkerCompletedEventHandler 
RunWorkerCompleted; public BackgroundWorker(); public void CancelAsync(); public void ReportProgress(int percentProgress); public void ReportProgress(
int percentProgress, object userState); public void RunWorkerAsync(); public void RunWorkerAsync(object argument); public bool CancellationPending { get; } public bool IsBusy { get; } public bool WorkerReportsProgress { get; set; } public bool WorkerSupportsCancellation { get; set; } }

As you can see, this API is really similar to the one we ended up after adding cancellation to the initial EAP implementation. The truth is that you can see this class as a reusable EAP implementation. You’ve got several events used for:

  • signaling the start of an asynchronous operation;
  • for reporting progress;
  • for notifying about the completion of an operation.

Asynchronous operations can be started through one of the two overloads of the RunWorkerAsync method.  This method ends up firing the DoWork event on a separated thread. You’re supposed to handle this event and put the code that should be run asynchronously in that method.

Cancellation is also available through the CancelAsync method. If you recall our previous discussion about the EAP pattern, then you know that this class supports only one asynchronous operation at a time (notice that the CancelAsync does not receive any object parameter). It’s also important to notice that you need to allow cancellations by setting the WorkerSupportsCancellation property to true.

Reporting is also available: you can use the ReportProgress method for marshalling report information back to the “main thread”. Anyone that is interested in reporting progress should handle the ProgressChanged event. The same observation we’ve made about cancellations is also valid for progress reporting: you need to enable it by setting the WorkerReportsProgress to true.

As you might expect, all the operations are supported through an internal AsyncOperation instance which is created when you invoke the RunWorkerAsync method. And I guess that’s it. With this post, we’ve ended our quick analysis on GUIs and multithreading. However, there’s still a lot of things to talk about multithreading, so I’ll keep writing about it. Stay tuned for more!