Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Asynchronous Invocation Using BackgroundWorker

3.72/5 (9 votes)
20 Jul 20062 min read 1   2.2K  
A simple article on implementing asynchronous code, in C#.

Sample Image

Introduction

When you have a function that takes a long time and it freezes the screen, the user gets nervous. They simply don't like to lose the control. It would give a friendly impression when they can still click on the form while the application is busy with getting the information, for example. When you start implementing asynchronous methods, you will wonder which technique is best suitable for your application. Would you use a Timer class or a Thread class or a BackgroundWorker? This article uses a BackgroundWorker class to show how easy it is, and where you need to pay attention when using it.

Background

I have tried to compare different methods of implementing Asynchronous Invocation in my weblog. With Microsoft Visual Studio 2005, I discovered this class which is new to me.

Using the code

I have put extra comments everywhere possible, to make the sample a snippet of code you can use to start your own implementation. The code implements a very simple action, which is finding files in a directory to simulate the time consuming action. This is the place where you need to change. For the rest, the skeleton should be kept the same.

The background worker is able to send an event to the called thread to change the screen appearance. That is very easy, and I thought it would be easy for everyone to discover. But what if that is not enough and you would like to send other messages back to the caller? So I used BeginInvoke to invoke a call on the caller thread.

I have two delegates used from the sub thread, to call the method implemented in the main thread.

C#
private delegate void PaintMessage(TreeNode root, 
                                   string childText);
private PaintMessage myAddNode = null;

The OnPaontMessage implements the adding of a newly found file into an existing (given) root. This is called when the sub-thread finds a new item.

C#
private delegate void EnableCancel(bool enabled);
private EnableCancel myEnableCancel = null;

The second delegate is to indicate that the thread has been started and that it could be stopped. It is implemented by the main thread to enable the Cancel button.

Starting the action will be done by calling the RunWorkerAsync method on the worker.

C#
this.backgroundWorker1.RunWorkerAsync(treeView1.Nodes[path]);

When a sub-folder is found, I send a notification to the main thread to create a node for the sub-folder. Then, I use that node to create a file node in it. But the dilemma is that I can not proceed with filling the file, if the main thread didn't get the chance to create the sub folder. Thus, I need to wait and let the main application take the chance to create it. One simple way to do this is the following loop:

C#
// Create a folder node before proceeding
IAsyncResult ar = BeginInvoke(myAddNode, new object[]
                  { root, di.Name });
// Update the screen

// Wait until the folder has been created before
// proceeding with the content of the folde
while (!ar.IsCompleted)
{
    Application.DoEvents();
    ar.AsyncWaitHandle.WaitOne(-1, false);
}

First, I invoke the delegate and I keep the reference to it. I use the reference to see if it has been completed. And in the loop, I let the application take the chance and do its events. Meanwhile, I tell my sub-thread to wait a bit.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here