.NET BackgroundWorker Summary
By Eric — — 3 minute readThe
System.ComponentModel.BackgroundWorker class
makes it easy to code a long running operation with the ability to
provide progress, cancellation, and notification of completion. It is
particularly nice for UI because while the long running operation
executes on a thread pool thread, notifications of progress and
completion are marshalled back to the "main" thread. (When I say "main"
thread, I mean the one on which BackgroundWorker.RunWorkerAsync() is
called.)
These are the steps for using BackgroundWorker:
Setup
- Create an instance of
System.ComponentModel.BackgroundWorker. This can be done manually, or by adding one as a component with the form designer if you're doing UI. Usually you want to store this in a member variable so that the instance is available from theDoWorkevent handler. - Add a handler for the
BackgroundWorker.DoWorkevent. This handler should implement the long running operation, and will be invoked from another thread. - If you want progress, add a handler for the
BackgroundWorker.ProgressChangedevent and set theBackgroundWorker.WorkerReportsProgressproperty to true. This event handler will be called on the "main" thread. If you forget to enable progress by setting the property, you'll get anInvalidOperationExceptionif you try to provide progress. - If you want to allow cancellation, set the
BackgroundWorker.WorkerSupportsCancellationproperty to true. Likewise, you'll get anInvalidOperaitonExceptionif you skip this step and try to cancel. - To get notification of completion, add a handler for the
BackgroundWorker.RunWorkerCompletedevent. This event handler will be called on the "main" thread when the long running operation stops, either because it is finished or it was cancelled.
Start
- Start the long running operation by calling
BackgroundWorker.RunWorkerAsync. You can optionally pass in an object that the long running operation can retrieve from theDoWorkEventArgs.Argumentproperty.
On the Main Thread
- Call
BackgroundWorker.CancelAsync()if the long running operation ought to be cancelled. Since the main thread isn't blocked, this could be in response to a Cancel button being pressed, for example. - Handle
ProgressChangedevents, if needed. TheProgressChangedEventArgs.ProgressPercentagecould be used to update a progress bar. Additional progress state can be passed from the long running operation through theProgressChangedEventArgs.UserStateproperty. - Handle the
RunWorkerCompletedevent. There are several properties on theRunWorkerCompletedEventArgsthat can be populated from the long running operation. TheErrorproperty has anExceptionobject if one was thrown in the long running operation. TheCancelledproperty tells whether the operation was cancelled (but see the steps on the worker thread below). TheResultproperty can be used to retrieve a final outcome of the long running operation.
On the Worker Thread
- Do whatever work is required. If the operation throws an
exception, the main thread can retrieve the exception from the
RunWorkerCompletedEventArgs.Errorproperty. - Check the
BackgroundWorker.CancellationPendingproperty. If the property is true, cancel the long running operation. Also, when the operation is cancelled, you should setDoWorkEventArgs.Cancelto true so that theRunWorkerCompletedEventArgs.Cancelledwill also be true. - Call
BackgroundWorker.ReportProgressas appropriate. You can pass a percent complete and an object with additional progress state if desired. - Set the
DoWorkEventArgs.Resultproperty when finished. The main thread can retrieve the result, if there is anything interesting to pass back to the main thread.
This post was inspired by Chapter 16 of Essential C# 2.0 by Mark Michaelis.