Skip to content

Latest commit

 

History

History
163 lines (105 loc) · 15.6 KB

walkthrough-implementing-a-form-that-uses-a-background-operation.md

File metadata and controls

163 lines (105 loc) · 15.6 KB
title ms.date dev_langs helpviewer_keywords ms.assetid description
Walkthrough: Implementing a Form That Uses a Background Operation
03/30/2017
csharp
vb
cpp
threading [Windows Forms], forms
BackgroundWorker component
background tasks
forms [Windows Forms], multithreading
threading [Windows Forms], walkthroughs
forms [Windows Forms], background operations
threading [Windows Forms], background operations
background operations
4691b796-9200-471a-89c3-ba4c7cc78c03
Learn how to use the BackgroundWorker class to perform time-consuming computations "in the background," while the user interface remains responsive.

Walkthrough: Implementing a Form That Uses a Background Operation

If you have an operation that will take a long time to complete, and you do not want your user interface (UI) to stop responding or to block, you can use the xref:System.ComponentModel.BackgroundWorker class to execute the operation on another thread.

This walkthrough illustrates how to use the xref:System.ComponentModel.BackgroundWorker class to perform time-consuming computations "in the background," while the user interface remains responsive. When you are through, you will have an application that computes Fibonacci numbers asynchronously. Even though computing a large Fibonacci number can take a noticeable amount of time, the main UI thread will not be interrupted by this delay, and the form will be responsive during the calculation.

Tasks illustrated in this walkthrough include:

  • Creating a Windows-based Application

  • Creating a xref:System.ComponentModel.BackgroundWorker in Your Form

  • Adding Asynchronous Event Handlers

  • Adding Progress Reporting and Support for Cancellation

For a complete listing of the code used in this example, see How to: Implement a Form That Uses a Background Operation.

Create a form that uses a background operation

  1. In Visual Studio, create a Windows-based application project called BackgroundWorkerExample (File > New > Project > Visual C# or Visual Basic > Classic Desktop > Windows Forms Application).

  2. In Solution Explorer, right-click Form1 and select Rename from the shortcut menu. Change the file name to FibonacciCalculator. Click the Yes button when you are asked if you want to rename all references to the code element 'Form1'.

  3. Drag a xref:System.Windows.Forms.NumericUpDown control from the Toolbox onto the form. Set the xref:System.Windows.Forms.NumericUpDown.Minimum%2A property to 1 and the xref:System.Windows.Forms.NumericUpDown.Maximum%2A property to 91.

  4. Add two xref:System.Windows.Forms.Button controls to the form.

  5. Rename the first xref:System.Windows.Forms.Button control startAsyncButton and set the xref:System.Windows.Forms.Control.Text%2A property to Start Async. Rename the second xref:System.Windows.Forms.Button control cancelAsyncButton, and set the xref:System.Windows.Forms.Control.Text%2A property to Cancel Async. Set its xref:System.Windows.Forms.Control.Enabled%2A property to false.

  6. Create an event handler for both of the xref:System.Windows.Forms.Button controls' xref:System.Windows.Forms.Control.Click events. For details, see How to: Create Event Handlers Using the Designer.

  7. Drag a xref:System.Windows.Forms.Label control from the Toolbox onto the form and rename it resultLabel.

  8. Drag a xref:System.Windows.Forms.ProgressBar control from the Toolbox onto the form.

Create a BackgroundWorker with the Designer

You can create the xref:System.ComponentModel.BackgroundWorker for your asynchronous operation using the Windows Forms Designer.

From the Components tab of the Toolbox, drag a xref:System.ComponentModel.BackgroundWorker onto the form.

Add asynchronous event handlers

You are now ready to add event handlers for the xref:System.ComponentModel.BackgroundWorker component's asynchronous events. The time-consuming operation that will run in the background, which computes Fibonacci numbers, is called by one of these event handlers.

  1. In the Properties window, with the xref:System.ComponentModel.BackgroundWorker component still selected, click the Events button. Double-click the xref:System.ComponentModel.BackgroundWorker.DoWork and xref:System.ComponentModel.BackgroundWorker.RunWorkerCompleted events to create event handlers. For more information about how to use event handlers, see How to: Create Event Handlers Using the Designer.

  2. Create a new method, called ComputeFibonacci, in your form. This method does the actual work, and it will run in the background. This code demonstrates the recursive implementation of the Fibonacci algorithm, which is notably inefficient, taking exponentially longer time to complete for larger numbers. It is used here for illustrative purposes, to show an operation that can introduce long delays in your application.

    [!code-cppSystem.ComponentModel.BackgroundWorker#10] [!code-csharpSystem.ComponentModel.BackgroundWorker#10] [!code-vbSystem.ComponentModel.BackgroundWorker#10]

  3. In the xref:System.ComponentModel.BackgroundWorker.DoWork event handler, add a call to the ComputeFibonacci method. Take the first parameter for ComputeFibonacci from the xref:System.ComponentModel.DoWorkEventArgs.Argument%2A property of the xref:System.ComponentModel.DoWorkEventArgs. The xref:System.ComponentModel.BackgroundWorker and xref:System.ComponentModel.DoWorkEventArgs parameters will be used later for progress reporting and cancellation support. Assign the return value from ComputeFibonacci to the xref:System.ComponentModel.DoWorkEventArgs.Result%2A property of the xref:System.ComponentModel.DoWorkEventArgs. This result will be available to the xref:System.ComponentModel.BackgroundWorker.RunWorkerCompleted event handler.

    [!NOTE] The xref:System.ComponentModel.BackgroundWorker.DoWork event handler does not reference the backgroundWorker1 instance variable directly, as this would couple this event handler to a specific instance of xref:System.ComponentModel.BackgroundWorker. Instead, a reference to the xref:System.ComponentModel.BackgroundWorker that raised this event is recovered from the sender parameter. This is important when the form hosts more than one xref:System.ComponentModel.BackgroundWorker. It is also important not to manipulate any user-interface objects in your xref:System.ComponentModel.BackgroundWorker.DoWork event handler. Instead, communicate to the user interface through the xref:System.ComponentModel.BackgroundWorker events.

    [!code-cppSystem.ComponentModel.BackgroundWorker#5] [!code-csharpSystem.ComponentModel.BackgroundWorker#5] [!code-vbSystem.ComponentModel.BackgroundWorker#5]

  4. In the startAsyncButton control's xref:System.Windows.Forms.Control.Click event handler, add the code that starts the asynchronous operation.

    [!code-cppSystem.ComponentModel.BackgroundWorker#13] [!code-csharpSystem.ComponentModel.BackgroundWorker#13] [!code-vbSystem.ComponentModel.BackgroundWorker#13]

  5. In the xref:System.ComponentModel.BackgroundWorker.RunWorkerCompleted event handler, assign the result of the calculation to the resultLabel control.

    [!code-cppSystem.ComponentModel.BackgroundWorker#6] [!code-csharpSystem.ComponentModel.BackgroundWorker#6] [!code-vbSystem.ComponentModel.BackgroundWorker#6]

Adding Progress Reporting and Support for Cancellation

For asynchronous operations that will take a long time, it is often desirable to report progress to the user and to allow the user to cancel the operation. The xref:System.ComponentModel.BackgroundWorker class provides an event that allows you to post progress as your background operation proceeds. It also provides a flag that allows your worker code to detect a call to xref:System.ComponentModel.BackgroundWorker.CancelAsync%2A and interrupt itself.

Implement progress reporting

  1. In the Properties, window, select backgroundWorker1. Set the xref:System.ComponentModel.BackgroundWorker.WorkerReportsProgress%2A and xref:System.ComponentModel.BackgroundWorker.WorkerSupportsCancellation%2A properties to true.

  2. Declare two variables in the FibonacciCalculator form. These will be used to track progress.

    [!code-cppSystem.ComponentModel.BackgroundWorker#14] [!code-csharpSystem.ComponentModel.BackgroundWorker#14] [!code-vbSystem.ComponentModel.BackgroundWorker#14]

  3. Add an event handler for the xref:System.ComponentModel.BackgroundWorker.ProgressChanged event. In the xref:System.ComponentModel.BackgroundWorker.ProgressChanged event handler, update the xref:System.Windows.Forms.ProgressBar with the xref:System.ComponentModel.ProgressChangedEventArgs.ProgressPercentage%2A property of the xref:System.ComponentModel.ProgressChangedEventArgs parameter.

    [!code-cppSystem.ComponentModel.BackgroundWorker#7] [!code-csharpSystem.ComponentModel.BackgroundWorker#7] [!code-vbSystem.ComponentModel.BackgroundWorker#7]

Implement support for cancellation

  1. In the cancelAsyncButton control's xref:System.Windows.Forms.Control.Click event handler, add the code that cancels the asynchronous operation.

    [!code-cppSystem.ComponentModel.BackgroundWorker#4] [!code-csharpSystem.ComponentModel.BackgroundWorker#4] [!code-vbSystem.ComponentModel.BackgroundWorker#4]

  2. The following code fragments in the ComputeFibonacci method report progress and support cancellation.

    [!code-cppSystem.ComponentModel.BackgroundWorker#11] [!code-csharpSystem.ComponentModel.BackgroundWorker#11] [!code-vbSystem.ComponentModel.BackgroundWorker#11] [!code-cppSystem.ComponentModel.BackgroundWorker#12] [!code-csharpSystem.ComponentModel.BackgroundWorker#12] [!code-vbSystem.ComponentModel.BackgroundWorker#12]

Checkpoint

At this point, you can compile and run the Fibonacci Calculator application.

Press F5 to compile and run the application.

While the calculation is running in the background, you will see the xref:System.Windows.Forms.ProgressBar displaying the progress of the calculation toward completion. You can also cancel the pending operation.

For small numbers, the calculation should be very fast, but for larger numbers, you should see a noticeable delay. If you enter a value of 30 or greater, you should see a delay of several seconds, depending on the speed of your computer. For values greater than 40, it may take minutes or hours to finish the calculation. While the calculator is busy computing a large Fibonacci number, notice that you can freely move the form around, minimize, maximize, and even dismiss it. This is because the main UI thread is not waiting for the calculation to finish.

Next steps

Now that you have implemented a form that uses a xref:System.ComponentModel.BackgroundWorker component to execute a computation in the background, you can explore other possibilities for asynchronous operations:

  • Use multiple xref:System.ComponentModel.BackgroundWorker objects for several simultaneous operations.

  • To debug your multithreaded application, see How to: Use the Threads Window.

  • Implement your own component that supports the asynchronous programming model. For more information, see Event-based Asynchronous Pattern Overview.

    [!CAUTION] When using multithreading of any sort, you potentially expose yourself to very serious and complex bugs. Consult the Managed Threading Best Practices before implementing any solution that uses multithreading.

See also