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.

Note

The dialog boxes and menu commands you see might differ from those described in Help depending on your active settings or edition. To change your settings, choose Import and Export Settings on the Tools menu. For more information, see Visual Studio Settings.

To run an operation in the background

  1. With your form active in the Windows Forms Designer, 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 Sub backgroundWorker1_DoWork( _
    sender As Object, e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
    
       ' Do not access the form's BackgroundWorker reference directly. 
       ' Instead, use the reference provided by the sender parameter. 
       Dim bw As BackgroundWorker = CType( sender, BackgroundWorker )
    
       ' Extract the argument. 
       Dim arg As Integer = Fix(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 Then
          e.Cancel = True 
       End If 
    
    End Sub
    
    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 Sub backgroundWorker1_RunWorkerCompleted( _
    sender As Object, e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted
    
       If e.Cancelled Then 
          ' The user canceled the operation.
          MessageBox.Show("Operation was canceled")
       ElseIf (e.Error IsNot Nothing) Then 
          ' There was an error during the operation. 
          Dim msg As String = String.Format("An error occurred: {0}", e.Error.Message)
          MessageBox.Show(msg)
       Else 
          ' The operation completed normally. 
          Dim msg As String = String.Format("Result = {0}", e.Result)
          MessageBox.Show(msg)
       End If 
    End Sub
    
    // 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 Function TimeConsumingOperation( _
    bw As BackgroundWorker, _
    sleepPeriod As Integer) As Integer 
    
       Dim result As Integer = 0
    
       Dim rand As New Random()
    
         While Not bw.CancellationPending
             Dim [exit] As Boolean = False 
    
             Select Case rand.Next(3)
                 ' Raise an exception. 
                 Case 0
                     Throw New Exception("An error condition occurred.")
                     Exit While 
    
                     ' Sleep for the number of milliseconds 
                     ' specified by the sleepPeriod parameter. 
                 Case 1
                     Thread.Sleep(sleepPeriod)
                     Exit While 
    
                     ' Exit and return normally. 
                 Case 2
                     result = 23
                     [exit] = True 
                     Exit While 
    
                 Case Else 
                     Exit While 
             End Select 
    
             If [exit] Then 
                 Exit While 
             End If 
         End While 
    
       Return result
    End Function
    
    // 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 Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click
        Me.backgroundWorker1.RunWorkerAsync(2000)
    End Sub
    
    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 Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
    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.

    Imports System
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Threading
    Imports System.Windows.Forms
    
    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.

  1. 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

Tasks

How to: Implement a Form That Uses a Background Operation

How to: Run an Operation in the Background

Reference

BackgroundWorker

DoWorkEventArgs

Other Resources

BackgroundWorker Component

Change History

Date

History

Reason

April 2009

Added a step to set the WorkerSupportsCancellation property to true.

Customer feedback.