Backgroundworker example

Posted in .NET 2.0 | Performance | Visual Studio 2005 at Tuesday, 10 February 2009 17:57 GMT Standard Time

The background worker allows you to execute intense or long operations on a separate thread, without having to deal with threads, invokes or delegates. This is essential in today's cluttered webspace brought forth by the constant growth of broadband technology.

This simple example pretty much cover all posibilities of use of this component: cancellation support, backgroundworker error handling and report progress (also passing UserState data on report progress notifications)

Nota: Este artículo está disponible en castellano aquí

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace BackgroundWorker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            //mandatory. Otherwise will throw an exception when calling ReportProgress method
            backgroundWorker1.WorkerReportsProgress = true; 

            //mandatory. Otherwise we would get an InvalidOperationException when trying to cancel the operation
            backgroundWorker1.WorkerSupportsCancellation = true;
        }



        //This method is executed in a separate thread created by the background worker.
        //so don't try to access any UI controls here!! (unless you use a delegate to do it)
        //this attribute will prevent the debugger to stop here if any exception is raised.
        //[System.Diagnostics.DebuggerNonUserCodeAttribute()]
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //NOTE: we shouldn't use a try catch block here (unless you rethrow the exception)
            //the backgroundworker will be able to detect any exception on this code.
            //if any exception is produced, it will be available to you on 
            //the RunWorkerCompletedEventArgs object, method backgroundWorker1_RunWorkerCompleted
            //try
            //{
                DateTime start = DateTime.Now;
                e.Result = "";
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(50); //do some intense task here.
                    backgroundWorker1.ReportProgress(i, DateTime.Now); //notify progress to main thread. We also pass time information in UserState to cover this property in the example.
                    //Error handling: uncomment this code if you want to test how an exception is handled by the background worker.
                    //also uncomment the mentioned attribute above to it doesn't stop in the debugger.
                    //if (i == 34)
                    //    throw new Exception("something wrong here!!");

                    //if cancellation is pending, cancel work.
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true; 
                        return;
                    }
                }

                TimeSpan duration = DateTime.Now - start;
                
                //we could return some useful information here, like calculation output, number of items affected, etc.. to the main thread.
                e.Result = "Duration: " + duration.TotalMilliseconds.ToString() + " ms.";
            //}
            //catch(Exception ex){
            //    MessageBox.Show("Don't use try catch here, let the backgroundworker handle it for you!");
            //}
        }


        
        //This event is raised on the main thread.
        //It is safe to access UI controls here.
        private void backgroundWorker1_ProgressChanged(object sender, 
            ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage; //update progress bar
            
            DateTime time = Convert.ToDateTime(e.UserState); //get additional information about progress
            
            //in this example, we log that optional additional info to textbox
            txtOutput.AppendText(time.ToLongTimeString());
            txtOutput.AppendText(Environment.NewLine);            
        }



        //This is executed after the task is complete whatever the task has completed: a) sucessfully, b) with error c)has been cancelled
        private void backgroundWorker1_RunWorkerCompleted(object sender, 
            RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled) {
                MessageBox.Show("The task has been cancelled");
            }
            else if (e.Error != null)
            {                
                MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
            }
            else {
                MessageBox.Show("The task has been completed. Results: " + e.Result.ToString());
            }
            
        }




        private void btoCancel_Click(object sender, EventArgs e)
        {
            //notify background worker we want to cancel the operation.
            //this code doesn't actually cancel or kill the thread that is executing the job.
            backgroundWorker1.CancelAsync();
        }

        private void btoStart_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

      
    }
}

Download sample project

Download BackgroundWorker.ZIP (C# sample project)

AddThis Social Bookmark Button

Thursday, 12 February 2009 18:23:40 (GMT Standard Time, UTC+00:00)
hello

I used BackgroundWorker for some ftp uploads. and I watch the process. at the end filezilla far more faster then mine do you have any idea why is that ?
Thursday, 12 February 2009 20:37:46 (GMT Standard Time, UTC+00:00)
I don't know filezilla but maybe it uses more than one thread (the backgroundWorker uses just one background thread) so it could complete the process faster if it has to upload more than one file (one upload per thread)
Monday, 16 February 2009 01:44:21 (GMT Standard Time, UTC+00:00)
If you are interested in learning how to exploit multicore processors, using threaded applications while updating the UI, you will find great examples in the book " C# 2008 and 2005 Threaded Programming: Beginners Guide", by Gaston Hillar, Packt Publishing - www.packtpub.com
It includes many exercises related to image management with multicore support. Highly recommended if you want to improve performance and UI responsiveness.
You can download the code from Packt's website. http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming
Highly recommended for C# developers.
Mike
Tuesday, 17 February 2009 16:21:57 (GMT Standard Time, UTC+00:00)
Hi Mike,

Thanks for the reference!
Next time I will charge you for the advertistment space though! :P
Wednesday, 18 February 2009 01:05:18 (GMT Standard Time, UTC+00:00)
Hi Ivan,

Just a recommendation. Unluckily, I am getting royalties with neither the publisher nor the author (they should send me a penny, because the book is published in England).
By the way, I love Backgroundworker! :-)

Cheers,
Mike
Mike
Saturday, 28 February 2009 17:21:23 (GMT Standard Time, UTC+00:00)
Hi,

I just wanted to tell you that the Source is completely obfuscated in RSS form.
It's completely unreadable without line breaks etc..

I really would suggest using the javascript syntaxhighlighter instead of creating a html tagsoup to color the code.

Your feed readers would really appreciate this :)

greetings,
Daniel
Sunday, 01 March 2009 07:44:04 (GMT Standard Time, UTC+00:00)
Hi Daniel,

You are very right. I had a look at http://alexgorbatchev.com/wiki/SyntaxHighlighter and I am quite impressed!
I will surely add it to this blog.

Thank you very much for the tip,

ivan
Sunday, 01 March 2009 21:15:50 (GMT Standard Time, UTC+00:00)
Well, I have already do it!

http://alexgorbatchev.com/wiki/SyntaxHighlighter is installed.

ivan
Sunday, 01 March 2009 23:09:57 (GMT Standard Time, UTC+00:00)
Great stuff. Thanks!
Sunday, 01 March 2009 23:12:19 (GMT Standard Time, UTC+00:00)
Sorry for the double-post, I forgot something :)

If you are using Windows Live Writer, I wrote a little plugin some time ago, that facilitates posting code with the syntaxhighlighter plugin.
It's hosted at CodePlex: http://www.codeplex.com/wlwPostCode

greetings Daniel
Friday, 06 March 2009 10:00:57 (GMT Standard Time, UTC+00:00)
Hi Daniel,

I have never used Windows Live Writer, I use the editor that comes with dasblog, that runs this blog.

Thanks again,

ivan
Thursday, 11 February 2010 16:25:23 (GMT Standard Time, UTC+00:00)
Thanks alot for this!

This helped me to understand how backgroundworker's work. Although I ran my database query in the backgroundworker. In the main thred I just had a progressbar with marquee style so that the user can see that the program is running in the background.

Cheers!
Wednesday, 31 March 2010 22:17:51 (GMT Daylight Time, UTC+01:00)
This was a great example that shows everything necessary to get you started. Thanx for the great job.

Dinos
Dino
Monday, 19 April 2010 12:32:45 (GMT Daylight Time, UTC+01:00)
I am new to c# and want to use progress bar in my application. the way that i want to use is that i have a button on which when i click, it runs an application like paint, notepad etc.
code is :
System.Diagnostics.Process Proc = new System.Diagnostics.Process();
Proc.StartInfo.FileName = comboBox1.Text;
prg = Proc.StartInfo.FileName;
i want to add progress bar that shows progress while the application is opening i.e when i press the start button, along with opening the application, progress bar also start. function is given under, what shoulid i add to it. i know nothing abt progress bar except adding it through drag and drop.
thanks in advance

private void statusStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
Friday, 28 May 2010 14:13:00 (GMT Daylight Time, UTC+01:00)
Hello,

Thank you very much for your code, but I have a problem...

You said:
//uncomment this code if you want to test how an exception is handled by the background worker.
//also uncomment the attribute above to it doesn't stop in the debugger.
Well, I did uncomment both:
if (i == 34)
throw new Exception("something wrong here!!");
and
[System.Diagnostics.DebuggerNonUserCodeAttribute()]

And still when I run the program, it throws the error and then the "DoWork" stops, Is there any possibility to make it doesn't stop no matter what? and that it continues?

Thank you,
ATDPRHS
ATDPRHS
Wednesday, 02 June 2010 14:27:14 (GMT Daylight Time, UTC+01:00)
Hi there,

If you want to ignore the exception, you can then use the try/catch and do whatever you want with it.
But if you do, the component won't be hable to notify you that a exception has been throwed.
Saturday, 19 June 2010 01:32:05 (GMT Daylight Time, UTC+01:00)
Why the process intensive task is in a loop, it means that it will run 100 times? Why? If it is out of loop that how one can manage progress bar?
lifeh2o
Saturday, 19 June 2010 14:36:33 (GMT Daylight Time, UTC+01:00)
The loop is just on example.

YOU have to notify progress bar how much is remaining or completed so:

1) if you have to repeat a number of times a certain operation (ex: processing 10, 200, 20000 files), it would be easy to calculate how much % is remaining, doing the math.
2) if you need ONE calculation or process, it is YOUR duty to inform progress bar how good are you doing and how much is remaining often, is up to you how you do it.

Progress bar has no information unless you supply to it.

In many cases, you don't know how long it is going to take (neither progress bar does), so you will have to "guess" and keep informed progress bar control.
Example: (processing an image about 20MB large you know it takes about 30 seconds, so you can increase progress bar value 10 points every 3 seconds while processing it)
Comments are closed.