Your DoWork
event handler shoud periodically check BackgroundWorker.CancellationPending
, and set DoWorkEventArgs.Cancel
to true before returning if it was cancelled.
Your RunWorkerCompleted
event handler should check the RunWorkerCompletedEventArgs.Cancelled
property to determine if the DoWork
event handler cancelled (set DoWorkEventArgs.Cancel
to true).
In the event of a race condition, it may happen that the user requested cancellation (BackgroundWorker.CancellationPending
is true) but the worker didn't see it (RunWorkerCompletedEventArgs.Cancelled
is false). You can test these two properties to determine that this has occurred, and do whatever you choose (either treat it as successful completion - because the worker did actually finish successfully, or as a cancellation - because the user has cancelled and doesn't care any more).
I don't see any situation where there is any ambiguity about what happened.
EDIT
In response to the comment - if there are several classes that need to detect CancellationPending
, there's no really no alternative to passing to these classes a reference to a type such as BackgroundWorker
that allows them to retrieve this information. You can abstract this into an interface, which is what I generally do as described in this response to a question about BackgroundWorkers. But you still need to pass a reference to a type that implements this interface to your worker classes.
If you want your worker classes to be able to set DoWorkEventArgs.Cancel
you will need to either pass a reference to this around, or adopt a different convention (e.g. a boolean return value or custom exception) that allows your worker classes to indicate that cancellation has occurred.