Friday, November 5, 2010

Use BackgroundWorker (1)

There are different ways to create multi-threading tasks such as:
1. Asynchronized Model Programming(AMP), I had an article about this before.
2. Parallel Programming, this is aslo used a lot in my daily work such as do parallel downloading of something, I will write an artile on this sometime later.
3. Threadpool.QueueUserworkItem to call back. Use the Threadpool is a traditional way dealing multi-threads tasks.
4. Use BackgroundWorker.

Let's look at the memebers of a BackgroundWorker first:

Let's first look into two event handler:

DoWork: This event handler will call the code in a seperate thread, and the event is fired by calling RunWorkerAsync method.

RunWorkerCompleted: This event occures when background thread completed or cancelled. Or an exception is raised.

and the method called RunWorkerAsync:

RunWorkerAsync: This method will fire the DoWork event.

We can write a simple code sample like:

using System;
using System.Threading;
using System.ComponentModel;

class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();

for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}

static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Background Thread writes: {0}", i.ToString());
Thread.Sleep(500);
}
}
}

The following picture shows the running result:



I. Pass parameters from main thread to background thread:

The parameters can be passed from main thread to background thread through include the parater in RunWorkerAsync method. The parameter will be passed to the DoworkEventArgs in background.

Here we change the code a bit:

using System;
using System.Threading;
using System.ComponentModel;

class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync(names);

for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}

static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Hello, {0}. Background Thread writes: {1}", ((string[])(e.Argument))[0], i.ToString());
Thread.Sleep(500);
}
}
}

In the above code, we pass the array to the background thread and used the array element here, the result is like the following picture.




II. Pass the background thread running result to main thread


The background thread runing result can also be passed to the Result property of the RunWorkerCompletedEventArgs parameter.

We write code example below:

using System;
using System.Threading;
using System.ComponentModel;

class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static object completedResult;
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
myWorker.RunWorkerAsync(names);

for (int i = 0;i<10; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(2000);
}
Console.WriteLine("The Calculation result from the background thread is:");
Console.WriteLine(completedResult??completedResult.ToString());
Console.Read();
}


static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Hello, {0}. Now we begin to calculating...", ((string[])e.Argument)[0]);
e.Result = myCal();

}

static void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
completedResult = e.Result;
}

static int myCal()
{
int i = 0;
for (int j = 0; j < 10; j++)
{
i += j;
Thread.Sleep(500);
}
return i;
}
}
The running result is like the following:



The sample code is placed at:

http://groups.google.com/group/jiezhu0815myfiles/web/BackgroundWorkerDemo.rar