~ Ready? ~
I’m going to just use a simple Windows Forms framework for my test code. WinForms is a pretty common denominator for most developers; just keep in mind that both
Task.Run are using
SynchronizationContext underneath, so these same principles apply regardless of platform (WPF, Windows Store, MonoTouch, MonoDroid, Windows Phone, Silverlight, ASP.NET, etc). I’m just using WinForms because it’s simple and pretty much everyone knows it.
The Basic Pattern: Do Work
The core problem that
BackgroundWorker originally solved was the need to execute synchronous code on a background thread. If you’re using
BackgroundWorker for asynchronous or parallel work then just stop; you’re not using the right tool in the first place. The core problem for
BackgroundWorker is to execute synchronous code on a background thread.
Our example (synchronous) action is just going to sleep for a second.
The Basic Pattern: Completion
In almost every real-world scenario, we also want to be notified when the background operation has completed. Also, most of the time, we want our “handle the completion” code to run on the original context (e.g., a UI context so we could update the UI). It would be best if this marshaling back to the UI thread could be automatic.
Our example completion code will just toss up a message box.
~ Fight! ~
Both of these are pretty straightforward. Both of them will marshal our
MessageBox.Show back to the UI thread, so we don’t have to worry about it.
BackgroundWorker code does suffer from more “ceremony”, since it has to deal with events. It’s also a bit awkward in that you have to wire up your events first and then explicitly start the work going. The equivalent
Task.Run is simpler - not a lot simpler, but simpler nonetheless.