How to use WPF Background Worker
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
BackgroundWorker is an older but still understandable way to run long work off the WPF UI thread. Its main value is simple progress reporting and completion callbacks without freezing the interface, although in newer WPF code many teams prefer Task, async, and await for the same job.
Configure the Worker and Its Events
A BackgroundWorker runs work on a background thread through DoWork, reports progress through ProgressChanged, and returns to the UI thread with RunWorkerCompleted.
This setup keeps the long-running work separate from button-click code and makes the lifecycle explicit.
Perform Work and Report Progress
The DoWork handler runs on a worker thread, so it is the place for long loops, CPU work, or blocking I/O that should not freeze the UI.
Use ReportProgress sparingly. Updating the UI too often can become its own performance problem.
Update the UI Safely
ProgressChanged and RunWorkerCompleted execute on the UI thread, so you can safely touch WPF controls there.
This is one of the reasons BackgroundWorker was popular: it hides most of the explicit thread-marshaling ceremony.
Support Cancellation Intentionally
If you expose a cancel button, connect it to CancelAsync and make sure the worker actually checks CancellationPending.
Cancellation is cooperative. If your DoWork handler never checks for it, the cancel request changes nothing.
When to Prefer Task and async
BackgroundWorker still works, but it is not the only option. In newer WPF code, Task.Run, async, and await often produce cleaner code, especially when your long-running work is already naturally asynchronous.
That said, BackgroundWorker remains understandable and serviceable in legacy WPF applications. If the surrounding codebase already uses it, consistency may matter more than modernization for its own sake.
Background workers can also accept startup arguments through RunWorkerAsync(argument), which is often cleaner than reading shared mutable state from inside DoWork. Passing explicit input makes the worker easier to test and reason about.
Common Pitfalls
Trying to update WPF controls directly inside DoWork breaks thread-affinity rules because that handler is not on the UI thread.
Calling CancelAsync without checking CancellationPending inside the worker creates fake cancellation support.
Reporting progress too frequently can make the UI busy even though the work is technically off the main thread.
Summary
- '
BackgroundWorkerruns long work off the WPF UI thread.' - Use
DoWorkfor the background operation,ProgressChangedfor UI progress, andRunWorkerCompletedfor final UI updates. - Cancellation is cooperative and must be checked explicitly.
- In modern WPF,
Taskandasyncare often cleaner, butBackgroundWorkeris still valid in legacy-style applications.
Related reading
- How to wait all spawned async tasks
- How to wait for a async void method to complete its task?
- How to wait for a BackgroundWorker to cancel?
- How to wait for a BackgroundWorker to cancel?
- how to use XPath with XDocument?
- How to use XPath with XElement or LINQ?
- How to wait for a JavaScript Promise to resolve before resuming function?
- How to wait for a number of threads to complete?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.