Welcome to weblogs.com.pk Sign in | Join | Help

Nasir Ali Khan

Believing is easier than thinking. Hence so many more believers than thinkers.
A Developers introduction to BackgroundWorker Component in .NET 2.0

Intended Readers: Persons having basic knowledge of multithreading, events and delegates
Platform: .NET 2.0
Level: Intermediate

Introduction
During the design of applications we often encounter problems in which multithreading or background processing is the appropriate solution. Tasks such as remote method invocation, File transfers, and database transactions are common examples.
.NET gives us a class called System.Threading.Thread for playing with background tasks, worker threads etc. Primary thread of application is responsible for creating the worker thread and controls its execution with methods such as suspend, resume etc. This approach has some draw backs such as

  • Threading logic is tightly coupled with application logic, results in-efficient design and less maintainability.
  • Progress tracking was very difficult and normally shared variables are used for keeping track of amount of work completed by the child thread.
  • In order to notify the completion of task, worker thread calls on or more methods of parent class and if parent class method contain any UI access statement then system will through an exception because controls of thread cannot be access by other.

Thread Pooling

You people might be wondering that isn’t Thread Pooling a proper solution, although it shields the thread manipulation logic from the application logic but it is designed specifically for waitable objects and it doesn’t contain the completion notification or progress tracking mechanism so what’s next? More here

The Mission
Instead of managing threads and delegates, .NET framework 2.0 introduces a new component System.ComponentModel.BackgroundWorker which provides high level and event based access to the background tasks and threads. From developers point of view its only a component which some properties, methods and events and we are not concerned with thread management, progress tracking or completion notification since all is automatically managed by the component with the help of events and methods (hmmmm Sounds cool).

The process of using BackgroundWorker is quite simple i.e.

  • Drag the component from toolbox
  • Add the event handler for DoWork event, this is background tasks.
  • Call one or more methods to notify the progress of tasks.
  • Add the event handler for RunWorkerCompleted, means end of tasks.

Isn’t it Simple and quick?

Before looking at the proper example of BackgroundWorker, let’s discuss some of the interested members of it.

  • DoWork (Event) Occurs when RunWorkerAsync method is called, handler of this event act as background thread.
  • ProgressChanged (Event) Occurs when worker thread calls ReportProgress method. This event gets chance to the main thread to determine the progress of tasks.
  • RunWorkerCompleted (Event) Occurs when the background operation has completed, has been canceled, or has raised an exception all the finishing logic will be included in the handler of this event.
  • CancelAsync (Method) Requests cancellation of a pending background operation after cancellation of tasks RunWorkerCompleted event will raise. This is normally called by the Parent thread.
  • ReportProgress (Method) Raises the ProgressChanged event, normally called by the component it self to inform the parent thread about the progress. 
  • RunWorkerAsync (Method) Starts execution of a background operation by raising DoWork event.

BackgroundWorker Component in Action 
The following demonstrate the use of  BackgroundWorker component, here background tasks takes ten seconds, and after every second it informs the progress to the main thread. In the end main thread display message box to inform the user.

Create Windows application in Visual Studio 2005 and add

  • Button, starts the background task
  • TextBox, which display progress of worker
  • BackgroundWorker component

Following is the code for the application

public partial class Form1 : Form
{
      ...
      private void button1_Click(object sender, EventArgs e)
      {
            // by default progress notification is false
            this.backgroundWorker1.WorkerReportsProgress = true;
            // starts the background task
            this.backgroundWorker1.RunWorkerAsync();
      }
 
      private void backgroundWorker1_DoWork_1(object sender, DoWorkEventArgs e)
      {
            MessageBox.Show("Work Start");
           
            for (int a = 1; a <= 10; a++)
            {
                  System.Threading.Thread.Sleep(1000);
                  // report progress to the main thread
                  backgroundWorker1.ReportProgress(a * 10);
            }
      }
 
      private void ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
            // update UI
            textBox1.Text = e.ProgressPercentage.ToString();
      }
 
      private void WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
            MessageBox.Show("Work Done...");
      }
}


Advantage of BackgroundWorker Component

  • Less effort on behalf of thread management.
  • High level, event based multi-threading.
  • Simple and efficient code.
  • Support of multiple tasks in one component, since DoWork is an event we can attach multiple handlers for it and thread will call each and every handler from the context of worker thread.
  • Since event handlers can be attached or detached at runtime, and background task is actually an event handler, this means we can dynamic attach or detach the task (isn’t it cool).
  • Support of progress notifications, worker thread can notify the parent about the percentage of task completed, by firing an event. Progress handlers can be multiple as well.

Conclusion
BackgroundWorker provides high level and event based support for creating the background tasks without involving into the threading issues. It also provides progress notification for the parent thread which was never there before. One instance of component also supports multiple tasks as well, and can be changed at runtime all we need to do is attach an event handler for the DoWork event. Use of BackgroundWorker component simplifies and improves the overall design of the application and most important very quickly.

Your Comments and feedbacks are always welcome

Posted: Sunday, August 21, 2005 8:02 PM by nasir

Comments

No Comments

Anonymous comments are disabled