Edit

Share via


Walkthrough: Running an Operation in the Background

If you have an operation that will take a long time to complete, and you do not want to cause delays in your user interface, you can use the BackgroundWorker class to run the operation on another thread.

For a complete listing of the code used in this example, see How to: Run an Operation in the Background.

Run an operation in the background

  1. With your form active in the Windows Forms Designer in Visual Studio, drag two Button controls from the Toolbox to the form, and then set the Name and Text properties of the buttons according to the following table.

    Button Name Text
    button1 startBtn Start
    button2 cancelBtn Cancel
  2. Open the Toolbox, click the Components tab, and then drag the BackgroundWorker component onto your form.

    The backgroundWorker1 component appears in the Component Tray.

  3. In the Properties window, set the WorkerSupportsCancellation property to true.

  4. In the Properties window, click on the Events button, and then double-click the DoWork and RunWorkerCompleted events to create event handlers.

  5. Insert your time-consuming code into the DoWork event handler.

  6. Extract any parameters required by the operation from the Argument property of the DoWorkEventArgs parameter.

  7. Assign the result of the computation to the Result property of the DoWorkEventArgs.

    This is will be available to the RunWorkerCompleted event handler.

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do not access the form's BackgroundWorker reference directly.
        // Instead, use the reference provided by the sender parameter.
        BackgroundWorker bw = sender as BackgroundWorker;
    
        // Extract the argument.
        int arg = (int)e.Argument;
    
        // Start the time-consuming operation.
        e.Result = TimeConsumingOperation(bw, arg);
    
        // If the operation was canceled by the user,
        // set the DoWorkEventArgs.Cancel property to true.
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
    }
    
  8. Insert code for retrieving the result of your operation in the RunWorkerCompleted event handler.

    // This event handler demonstrates how to interpret
    // the outcome of the asynchronous operation implemented
    // in the DoWork event handler.
    private void backgroundWorker1_RunWorkerCompleted(
        object sender,
        RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            // The user canceled the operation.
            MessageBox.Show("Operation was canceled");
        }
        else if (e.Error != null)
        {
            // There was an error during the operation.
            string msg = String.Format("An error occurred: {0}", e.Error.Message);
            MessageBox.Show(msg);
        }
        else
        {
            // The operation completed normally.
            string msg = String.Format("Result = {0}", e.Result);
            MessageBox.Show(msg);
        }
    }
    
  9. Implement the TimeConsumingOperation method.

    // This method models an operation that may take a long time
    // to run. It can be cancelled, it can raise an exception,
    // or it can exit normally and return a result. These outcomes
    // are chosen randomly.
    private int TimeConsumingOperation(
        BackgroundWorker bw,
        int sleepPeriod )
    {
        int result = 0;
    
        Random rand = new Random();
    
        while (!bw.CancellationPending)
        {
            bool exit = false;
    
            switch (rand.Next(3))
            {
                // Raise an exception.
                case 0:
                {
                    throw new Exception("An error condition occurred.");
                    break;
                }
    
                // Sleep for the number of milliseconds
                // specified by the sleepPeriod parameter.
                case 1:
                {
                    Thread.Sleep(sleepPeriod);
                    break;
                }
    
                // Exit and return normally.
                case 2:
                {
                    result = 23;
                    exit = true;
                    break;
                }
    
                default:
                {
                    break;
                }
            }
    
            if( exit )
            {
                break;
            }
        }
    
        return result;
    }
    
  10. In the Windows Forms Designer, double-click startButton to create the Click event handler.

  11. Call the RunWorkerAsync method in the Click event handler for startButton.

    private void startBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.RunWorkerAsync(2000);
    }
    
  12. In the Windows Forms Designer, double-click cancelButton to create the Click event handler.

  13. Call the CancelAsync method in the Click event handler for cancelButton.

    private void cancelBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.CancelAsync();
    }
    
  14. At the top of the file, import the System.ComponentModel and System.Threading namespaces.

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
    
  15. Press F6 to build the solution, and then press Ctrl+F5 to run the application outside the debugger.

    Note

    If you press F5 to run the application under the debugger, the exception raised in the TimeConsumingOperation method is caught and displayed by the debugger. When you run the application outside the debugger, the BackgroundWorker handles the exception and caches it in the Error property of the RunWorkerCompletedEventArgs.

  16. Click the Start button to run an asynchronous operation, and then click the Cancel button to stop a running asynchronous operation.

    The outcome of each operation is displayed in a MessageBox.

Next steps

See also