Geeks With Blogs
Deeksha Sharma
BackgroundWorker Basics in C#

This will be my first tutorial so I hope I can make myself clear. Also English isn't my first language so I apologize in advance for the inevitable language errors. ;)

Attached Image

What will this tutorial cover?

Making the BackgroundWorker do useful work for you, how to get the results back(I'm using List<int> as returndata, passing parameters to the BackgroundWorker, keeping track of progress and cancel the background process while it's running. Finally I'll show a way of collecting the results from the BackgroundWorker “on the fly” instead of waiting for all the calculations to be done.


Why use the BackgroundWorker?

You can use it to shift some heavy calculations, for example database access or file searching, to another thread and make the user interface more responsive. If both UI and the heavy calculations are ran within the same thread the UI appears to hang, making the average pc user think the program has crashed. So let's do it the decent way and use BackgroundWorker! 

How to use the BackgroundWorker?

The BackgroundWorker may sound quite intimidating, but actually it's very easy and intuitive to do use once you've done the first time. So let's get going and make a simple application showing you the usage of the BackgroundWorker. In case you want to look up the BackgroundWorker class on MSDN, it's in the System.ComponentModel namespace.

The first thing you need to do is to add the BackgroundWorker to the application and the easiest way to do so is to drag it from the toolbox onto your form. It's under the components tab. You'll see the BackgroundWorker showing up as BackgroundWorker1 in the gray box under your form.
Attached Image

The BackgroundWorker is event-driven, so what you need to do to get the basics working is this:
-Invoke the BackgroundWorker's DoWork class from your application.
-Give DoWork some work to do by adding the code in the BackgroundWorker1.DoWork method.
-After the code in the DoWork method is done, the event RunWorkerCompleted is invoked.
-Through the RunWorkerCompleted method, we'll retrieve our return values from the 2nd thread

Ok, lets get coding! Double click on the DoWork event and add:

01private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
02        {
03            List<int> temp = new List<int>();//our simulated return data
04            for (int i=0; i<= 10; i++)
05            {
06                Thread.Sleep(300);//used to simulate lengthy operations,
07                temp.Add(i);//in this case 10*300ms=3s(add using System.Threading)
08            }
09            e.Result = temp;//return temp
10        }

And now for the RunWorkerCompleted event:

1private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
2        {
3            data.AddRange((List<int>)e.Result);//copies return value to public list we declared before
4            MessageBox.Show("Done");
5        }


Finally make a button, change the text to Start, and add the following to the Button.Click event:


1private void button1_Click(object sender, EventArgs e)
2        {
3            backgroundWorker1.RunWorkerAsync();//this invokes the DoWork event
4        }

How do I pass an argument to the BackgroundWorker?

That's very easy. Let's try and pass the time the thread sleeps as an argument. First change the way we invoke the DoWork event to:

1private void button1_Click(object sender, EventArgs e)
2        {
3            backgroundWorker1.RunWorkerAsync(300);//300 gives a total of 3 seconds pause
4        }

And use the argument in our BackgroundWorker by changing the code to:

01private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
02        {
03            int time = (int)e.Argument;
04            List<int> temp = new List<int>();//our return data
05            for (int i=0; i<= 10; i++)
06            {
07                Thread.Sleep(time);//used to simulate lengthy operations,
08                temp.Add(i);//in this case 10*300ms=3s(add using System.Threading)
09            }
10            e.Result = temp;//return temp
11        }

How do I cancel a BackgroundWorker operation halfway?

First set the WorkerSupportsCancellation property to true in the property window. Now add a button with text “Cancel”, double click on it and add:

1private void button2_Click(object sender, EventArgs e)
2        {
3            backgroundWorker1.CancelAsync();//makes the backgroundworker stop
4        }

Now we need to make the BackgroundWorker check if it has gotten the order to stop, and then break out of the loop. To do so, change the code to:

01private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
02        {
03            int time = (int)e.Argument;
04            List<int> temp = new List<int>();//our return data
05            for (int i=0; i<= 10; i++)
06            {
07                if (backgroundWorker1.CancellationPending)//checks for cancel request
08                {
09                    e.Cancel = true;
10                    break;
11                }
12                Thread.Sleep(time);//used to simulate lengthy operations,
13                temp.Add(i);//in this case 10*300ms=3s(add using System.Threading)
14            }
15            e.Result = temp;//return temp
16        }


Now if we press cancel, we get into trouble, so we also need to change RunWorkerCompleted to check for cancellations:


01private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
02        {
03            if (e.Cancelled)//it doesn't matter if the BG worker ends normally, or gets cancelled,
04            {              //both cases RunWorkerCompleted is invoked, so we need to check what has happened
05                MessageBox.Show("You've cancelled the backgroundworker!");
06 
07            }
08            else
09            {
10                data.AddRange((List<int>)e.Result);//copies return value to public list we declared before
11                MessageBox.Show("Done");
12            }
13        }

How do I keep track of progress?

First set the WorkerReportsProgress property to true. Then change the DoWork method to:

01private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
02        {
03            int time = (int)e.Argument;
04            List<int> temp = new List<int>();//our return data
05            for (int i=0; i<= 10; i++)
06            {
07                if (backgroundWorker1.CancellationPending)//checks for cancel request
08                {
09                    e.Cancel = true;
10                    break;
11                }
12                backgroundWorker1.ReportProgress(i * 10);//reports a percentage between 0 and 100
13                Thread.Sleep(time);//used to simulate lengthy operations,
14                temp.Add(i);//in this case 10*300ms=3s(add using System.Threading)
15            }
16            e.Result = temp;//return temp
17        }

Now create a new ProgressBar, and then double click on the BackgroundWorker's ProgressChanged event and add:

1private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
2        {
3            progressBar1.Value = e.ProgressPercentage;
4        }

Is there any other use for WorkerReportsProgress?

Yes there is. Let's say that instead of calculating all data, and then passing it on like we did, you want to add data “on the go”. For this we can use the Userstate parameter, which we can use to return any object, and then in the ProgressChanged event handler, we can cast this into the appropriate type and do with it whatever you need. As an example we'll use the values of i we looped through and add them to a second list. To keep it short, change:

1backgroundWorker1.ReportProgress(i*10);

into:

1backgroundWorker1.ReportProgress(i * 10,i);//reports ProgressPercentage AND Userstate

Now let's collect the data in a second List<int>:

1private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
2        {
3            progressBar1.Value = e.ProgressPercentage;
4            data_new.Add((int)e.UserState);//casts the userstate into integer and adds it to a List
5             
6        }





http://books.google.co.in/books?id=4C-wInTw8uwC&pg=PT620&lpg=PT620&dq=operation+has+been+cancelled+backgroundworker&source=bl&ots=kvq3MJL7u3&sig=hgFLfA9Nl9tG8FzibZn2Bo2lw1E&hl=en&sa=X&ei=-7YjVJ2HKoyWuATR34LYBw&ved=0CDUQ6AEwAw#v=onepage&q=operation%20has%20been%20cancelled%20backgroundworker&f=false
Posted on Tuesday, September 23, 2014 5:52 AM | Back to top


Comments on this post: using the BackgroundWorker

# re: using the BackgroundWorker
Requesting Gravatar...
Great help
Left by vishal on Sep 26, 2014 12:23 AM

Your comment:
 (will show your gravatar)


Copyright © Deeksha Sharma | Powered by: GeeksWithBlogs.net