In this series on Task.Run vs BackgroundWorker, we’ve looked at the most common aspects of running background tasks. As a recap, here’s the full list of posts in chronological order:
- Introduction - we’re only contrasting
BackgroundWorkerfor situations that
BackgroundWorkerwas designed for.
- Round 1: Basics - how to run code on a background thread and receive a completion notification marshaled back to the UI thread. The
Task.Runcode is shorter and simpler with less “ceremony code”.
- Round 2: Errors - how to handle exceptions from the background thread code. The
Task.Runcode uses the more natural and less error-prone
try/catchblocks, and has less error-prone exception propagation.
- Round 3: Results - how to retrieve a result value from the background thread. The
Task.Runcode uses the more natural
returnstatement and the result value is strongly-typed.
- Round 4: Cancellation - how to cancel the background thread. The
Task.Runcode uses the common cancellation framework, which is simpler, less error-prone, and interoperates more cleanly with other cancellation-aware APIs.
- Round 5: Progress Reports - how to support progress updates from the background thread. The
Task.Runcode uses a strongly-typed progress report type.
What I am not planning to cover in this series are more complex situations, which is actually where
Task.Run really outperforms
BackgroundWorker. For example, nesting one background operation within another is easier with
Task.Run. Also, anything like waiting for two separate background operations to complete before doing something else is much easier with
Task.Run. Pretty much any time you have to coordinate background operations,
Task.Run code is going to be much simpler!
I hope that this series is sufficient to convince you that
BackgroundWorker is a type that should not be used in new code. Everything it can do,
Task.Run can do better; and
Task.Run can do a lot of things that
I’ll leave you with a “combined” example. The code below starts a cancelable background operation that reports progress, and will either throw an exception or return a value. These are all the basic operations of
BackgroundWorker. One of these uses
BackgroundWorker and the other uses
Task.Run. Don’t just look at the length of the code; consider all the little nuances of how it works (type safety, how easily the API can be misused, etc). Then ask yourself: which code would I rather maintain?