.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 theDoWork
event handler. - Add a handler for the
BackgroundWorker.DoWork
event. 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.ProgressChanged
event and set theBackgroundWorker.WorkerReportsProgress
property 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 anInvalidOperationException
if you try to provide progress. - If you want to allow cancellation, set the
BackgroundWorker.WorkerSupportsCancellation
property to true. Likewise, you'll get anInvalidOperaitonException
if you skip this step and try to cancel. - To get notification of completion, add a handler for the
BackgroundWorker.RunWorkerCompleted
event. 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.Argument
property.
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
ProgressChanged
events, if needed. TheProgressChangedEventArgs.ProgressPercentage
could be used to update a progress bar. Additional progress state can be passed from the long running operation through theProgressChangedEventArgs.UserState
property. - Handle the
RunWorkerCompleted
event. There are several properties on theRunWorkerCompletedEventArgs
that can be populated from the long running operation. TheError
property has anException
object if one was thrown in the long running operation. TheCancelled
property tells whether the operation was cancelled (but see the steps on the worker thread below). TheResult
property 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.Error
property. - Check the
BackgroundWorker.CancellationPending
property. If the property is true, cancel the long running operation. Also, when the operation is cancelled, you should setDoWorkEventArgs.Cancel
to true so that theRunWorkerCompletedEventArgs.Cancelled
will also be true. - Call
BackgroundWorker.ReportProgress
as appropriate. You can pass a percent complete and an object with additional progress state if desired. - Set the
DoWorkEventArgs.Result
property 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.