Working with BackgroundWorker & Create your own loading class


February 19, 2009
Feedback's a good way to encourage author even if it's a criticize. It's proved you care about the article. Please, leave a comment to let everyone know what you think about this post.

another tip »

Source code: TestLoading

It's always annoying when I run an application, click a button, the whole application become freezing. You don't know that's it's crashed or it's still working. Try to click on any other button, we will get the message Not response or something like that.

bw1

That's not sound like a modern application isn't it. So don't make your application like that. Whenever your application start run a big slow methods, make sure your inform your user about that.

BackgroundWorker is there to help you solve this problem. With this you don't need to worry about how Asynchronies method work. To inform users your application is running, create a Loading Form, run the BackgroundWorker, show up the Loading Form. Whenever the backgroundworker completed, close the form.

bw2

Simple right? But I want more. For me, reusable is also important. I need to use Loading Form in different applications, different form. I can't be ask to create a backgroundworker for every forms, every functions I need it.

So I also create my own Class/Library to help my life easier. This class will auto-create a backgroundworker, run the code, show the form, and close the form when it finishes. This is one of my favorite class in my Utilities Belt Library (I have my utilities class which I use it for almost every project I working on, can't live without it)

If you don't know about the basic BackgroundWorker, you should read the ?Basic BackgroundWorker? part. If you just want to know to know more about how I create my class, scroll down to the ?Make your own class? part.

Basic BackgroundWorker

BackgroundWorker is a simple(simplest maybe) way to make your app run multi-threading. To using it:

  • Insert a new BackgroundWorker into your form.
  • Insert your function into DoWork event.
private void bWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    decimal ThisMaxValue = Maximum;
    if(e.Argument!=null && e.Argument is decimal)
        ThisMaxValue = (decimal)e.Argument;
    //This run in a new thread
    for (int i = 0; i <= ThisMaxValue; i++)
    {
        Idx = i;
    }
}	
  • [Optional] Insert some command into RunWorkerCompleted if needed.
    private void bWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        nudShowResult.Value = Idx;
        timer1.Stop();
        if (LoadingForm != null && LoadingForm.Visible)
            LoadingForm.Dispose();
    }
  • Start running BackgroundWorker.
    private void button4_Click(object sender, EventArgs e)
    {
        timer1.Start();
        bWorker1.RunWorkerAsync();
        LoadingForm = new FrmLoading();
        LoadingForm.ShowDialog();
    }

    Make sure  to show the form after run the backgroundworker. If not, the backgroundworker won't run ask it need to wait for the form to close first.

    Create a timer if you need to update the value into a control:

    private void timer1_Tick(object sender, EventArgs e)
    {
        nudShowResult.Value = Idx;
    }

    The function in BackgroundWorker is not allowed to access any controls because it in different thread. Failed to do so, you will get a really really slow error report. So make sure you don't point to any control in the DoWork event.

To running BackgroundWorker function with argument, you could do like this:

	bWorker1.RunWorkerAsync(decimal.Parse(textBox1.Text));

The extract the arguement from eventArgs

if(e.Argument!=null && e.Argument is decimal)
    ThisMaxValue = (decimal)e.Argument; 

You could check on my code file for more detail if necessary.

Make your own class

This class isn't exactly what in my Utilities belts class. This is made for this tutorial purpose only.

So what we need:

Create a new Library project and add System.Windows.Form into your project references.

Add those using into your class file:

using System.Windows.Forms;
using System.ComponentModel;

Add a new form for loading form. It will show up every time the BackgroundWorker start and close when it finishes.

Declare a delegrate void. Using this to pass a function into your class

public BackgroundWorker Bw;
public delegate void RunFunction();

Add some variables for the class.

public BackgroundWorker Bw;
public RunFunction thisFunction;
LoadingForm newLoading; 

The construction will be like this.

public BackgroundLoading(RunFunction newFunction)
{
    thisFunction = newFunction;
    Bw = new BackgroundWorker();
    Bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
    Bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted);
}

newFunction is what will run in DoWork event. Create a new BackgroundWork and add event handler for it.

Basic simple code for those event handler

void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    newLoading.Dispose();
    MessageBox.Show("Complete");
} 

void Bw_DoWork(object sender, DoWorkEventArgs e)
{
    if (thisFunction != null)
        thisFunction();
} 	

Add a start function, which will run the BackgroundWorker and show up the loading form.

public void Start()
{
    Bw.RunWorkerAsync();
    newLoading = new LoadingForm();
    newLoading.ShowDialog();
}

That's it for the simple loading class.

Using this class

Add a method, this will run asynchrony.

public void Counter()
{
    for (int i = 0; i <= Maximum; i++)
    {
        Idx = i;
    }
}

Create a new class and associate the new method with this class. Then run the class by using its Start method.

private void button5_Click(object sender, EventArgs e)
{
    LoadingClass.BackgroundLoading BL = new LoadingClass.BackgroundLoading(Counter);
    BL.Start();
} 

That's it! You could try the code examples to see how it really work.

Conclusion

BackgroundWorker is a great control which help us to run multi-thread much easier. Using it effectively could make your app much more professional and user friendly.

As I only try to cover a basic approach to BackgroundWorker, the class was just a simple example. There are a lot of room to improve it. You could add a timer to see how long it run, or add a gif animation to make it look cool?

Hope you enjoy this .

Tags: ,,,

  • Delicious

Some more useful articles for you

Under Category: App Development
Article Tags: ,
Leave a Reply