BackgroundWorker Threads and Supporting Cancel
September 25, 2007
Check out the code here: BackgroundWorker Threads on CodeProject
This article is for novice and amateur developers who recognize areas of their application that could use threading but don’t want to be burdened with some of the complexity that comes with threading. Threading is a concept that many programmers tend to avoid because it can be difficult to understand, debug and implement. You can develop a very sophisticated multi-threaded application using C#. Don’t worry the
BackgroundWorker object makes threading easy to use, even if you don’t want to take the time to understand everything about threading.
When your application loads it runs on a single thread, this is referred to as the UI thread. Generally this is the thread that all of your UI objects have been created on and this is the thread that all of your code execution is performed on. The UI also uses this single thread to paint the UI objects. So when you’re running a long task, like processing some unknown number of MP3 files in a directory your application locks up, the window turns white, the user can’t click any buttons, the title bar changes to “My Cool App (Not Responding)”. So you go back and put in a bunch of
Application.DoEvents() calls into you MP3 crunching function and all
is better again… Except not really, the code runs slower now and the form still locks up but only for short spirts. The whole application seems a bit choppy.
What you need to do is do this heavy processing on a different thread. Leave the UI thread free for painting the UI. .Net has made the
BackgroundWorker object available to us to simplify threading. This object is designed to simply run a function on a different thread and then call an event on your UI thread when it’s complete. The steps are simple, create a
BackgroundWorker object tell it what function to run on the Background thread (the
DoWork function), tell it what function to run on the UI thread when the work is complete (the
RunWorkerCompleted function), then tell the
BackgroundWorker object to go to work.
There is one rule you need to be aware of, you can’t access UI objects on a thread that didn’t create them. Therefore you would receive a runtime error if you wrote the line of code
lblStatus.Text = “Processing file 5 of 100”; in the
DoWork function. There are two ways around this and I use both in the examples. The BackgroundWorker object resolves this problem by giving us a
ReportProgress function which can be called from the Background thread’s
DoWork function, this will cause the
ProgressChanged event to fire on the UI thread. Now we can access the UI objects on their thread and do what we want. But what if I just need to update a label or disable a button while on the BackGround thread, no problem, using
Control.Invoke you can supply some code (in an anonymous function) to be ran on the UI thread, I use this technique in the Asynchronous example to update the Progress Form’s label and progress bar.
Check out how I solve these problems in my CodeProject article: BackgroundWorker Threads