Thursday, January 4, 2007

Using the BackgroundWorker

The backgroundworker component is a new component in .NET 2.0 that allows you to easily run costly processes in the background. This way the user interface is not blocked.

In this sample I'm using the BackgroundWorker to read a 12MB large xml file in a dataset. After the xml file is read, I'll show its contents in a datagrid on a WinForms application. When refreshing the grid you will see that the UI is not blocked.

Here we go:

  • Create a new WinForms application (the example code is written in C#)

  • Add a Button and a DataGridView control to the form

  • Add a BackgroundWorker component to the form

  • Double click on the DoWork and RunWorkerCompleted events in the propertygrid to create the associated methods

  • The code in the DoWork event handler is run on a separate and dedicated thread.
    Here we will add the code to read the xml file in a dataset and return it to the calling method.

    Copy the following code in the DoWork eventhandler (explanation will folow):
    private void backgroundWorker1_DoWork(object sender,
    DoWorkEventArgs e)
    {
    // Use the parameter that has been passed
    string fileName = (string)e.Argument;

    // Load the file in the dataset
    DataSet ds = new DataSet();
    ds.ReadXml(fileName);

    // Set the dataset to the result property to make it
    // available to the calling thread

    e.Result = ds;
    }



    To pass a parameter to the background thread we can use the DoWorkEventArgs.Argument property.
    To pass the result back to the calling thread, we use the DoWorkEventArgs.Result property.
  • When the background process is finished, we need to do something with the result. This is done in the RunWorkerCompleted eventhandler. The following code retrieves the DataSet out of the Result property from the RunWorkerCompletedEventArgs argument.

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    // Get the dataset out of the result property
    DataSet xmlContent = (DataSet)e.Result;

    // Bind the dataset to the gridview
    dgvXmlContent.DataSource = xmlContent.Tables[0];
    }
  • Now the only thing that rests us is tell the BackgroundWorker to start.

    private void btnLoadXML_Click(object sender, EventArgs e)
    {
    string fileName = @"C:\Sample.xml";
    backgroundWorker1.RunWorkerAsync(fileName);
    }

That's all there is to it. When the data is loaded and you click again on the Load button, you will see that you can continue working with the grid. At a certain moment, it will flash indicating that a new databinding has occured.

3 comments:

Bart Bultinck said...

Thx! didn't know about that one !

Geert Verhoeven said...

Glad I could help. Nice blog by the way.

Kris Komar said...

This is AWESOME! Been looking for this all over the net. THANKS SO MUCH!