C#. Windows Forms. The BackgroundWorker control. Displays the progress of completed work. Canceling the execution of a thread




The BackgroundWorker control. Displays the progress of completed work. Canceling the execution of a thread

This topic is a continuation of the topic:


Contents


Search other websites:

1. Scheme for visualizing the progress of the completed work in the thread

Figure 1 shows a diagram of the interaction between event handlers to display progress in the thread (background operation). On the basis of this scheme, an algorithm is described that describes the progress of the work performed (see section 2).

C#. Windows Forms. Control BackgroundWorker. Visualization of the progress of completed work

Figure 1. Visualization of the progress of completed work

 

2. Algorithm for visualizing the progress of completed work

To display the progress of the completed work (progress) in the thread, you need to use the following elements of the BackgroundWorker class:

  • property WorkerReportProgress;
  • method ReportProgress().

The sequence of actions for displaying the progress of a thread is as follows.

1. In design mode, set the property WorkerReportProgress = true.

2. In the DoWork event handler, call the ReportProgress method, in which you specify the percentage of work completed.

For example, if the thread runs a normal loop from 1 to 100, then the code for setting the percentage will be something like this:

// The event handler DoWork
private void backgroundWorker1_DoWork(...)
{
  // ...

  for (i = 1; i<=100; i++)
  {
    // Actions performed in a loop
    // ...

    // Call the handler for the ProgressChanged event
    try
    {
      backgroundWorker1.ReportProgress((i*100)/100);
    }
    catch(InvalidOperationException exception)
    {
      MessageBox.Show(exception.Message);
    }
  }
}

where backgroundWorker1 is the name of the thread instance for which you want to display the task progress.

3. In the handler for the ProgressChanged event, display the percentage value in some visual component. The percentage value itself is derived from the e instance of the ProgressChangeEventArgs data class.

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  // Display percentage in label1.Text
  label1.Text = Convert.ToString(e.ProgressPercentage) + "%";

  // Show percentage change in progressBar1.Value
  progressBar2.Value = e.ProgressPercentage;
}

here

  • label1 – a control that displays a percentage value (for example, 28%);
  • ProgressChangeEventArgs – a class that represents data for the ProgressChanged event;
  • e.ProgressPercentage – a property that returns an integer percentage that was generated in step 2 of the algorithm when the ReportProgress() method was called.

 

3. Cancel execution of the thread. Scheme of interaction between event handlers

When executing some thread (background operation), the user has the ability to cancel the execution of this thread. The BackgroundWorker class has all the necessary controls for canceling the execution of a thread. Figure 2 shows the interaction between the event handlers that are involved in canceling the execution of a thread.

C#. Windows Forms. BackgroundWorker class. Cancel execution of the thread

Figure 2. Cancel execution of the thread. Interaction between event handlers

 

4. Sequence of actions (algorithm) for canceling the execution of a thread

It describes actions that need to be performed in order to correctly handle the cancellation of the execution of a thread (background operation). The following related members of the BackgroundWorker class are used to cancel a thread:

  • property WorkerSupportsCancellation;
  • method CancelAsync();
  • property CancellationPending.

The algorithm that implements the correct cancellation of the execution of a thread is as follows.

1. Set the property WorkerSupportsCancellation = true. This will allow you to use the means of stopping (canceling) the thread.

2. Call the CancelAsync() method in the event handler of the click on the button to stop the thread

// Cancel the thread execution
private void button2_Click(object sender, EventArgs e)
{
  try
  {
    backgroundWorker1.CancelAsync();
  }
  catch(InvalidOperationException exception)
  {
    // Display the error message
    MessageBox.Show(exception.Message);
  }
}

Now, when you click on the button to stop the thread, a corresponding request will be generated in the DoWork event handler.

3. In the DoWork event handler, check whether the command to stop the thread has been invoked. This is accomplished by checking the CancellationPending property.

In the simplest case, for a normal loop, the thread stopping code will look like this:

...

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

  ...

  // Thread execution loop
  for (int i=0; i<1000; i++)
  {

    ...

    // Checking if a thread cancellation command has been executed
    if (backgroundWorker1.CancellationPending)
      break; // if there was a request to stop the thread, then exit the loop
  }
}

...

4. In the handler for the RunWorkerCompleted event, take the appropriate action after the thread finishes executing.

In order to recognize the way the stream ends, you can enter an additional internal variable that will take on the appropriate value. The following code introduces an internal variable fCancelled into the form class. This variable determines whether the thread was canceled by the user and whether it is raised in the DoWork event handler. The event handler text is as follows.

The result of the completion of the thread execution (normal completion or canceled by the user) is displayed in the handler for the RunWorkerCompleted event. Also in this handler, the fCancelled variable is set to its original state.

// Form class
public partial class Form1 : Form
{
  // Determines how the thread was terminated
  bool fCancelled = false; // if fCancelled = false, then the thread execution was canceled by the user

  ...

  // Thread execution - DoWork event handler - sets fCancelled value
  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
  {

    ...

    // Thread execution loop
    for (int i=0; i<1000; i++)
    {

      ...

      // Checking if a thread cancellation command has been executed
      if (backgroundWorker1.CancellationPending)
      {
        // indicate that the thread execution was canceled by the user
        fCancelled = true;

        // end the thread, exit the loop
        break;
      }
    }
  }

  // Thread termination event handler
  private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
    // Checking how the thread was terminated
    if (fCancelled)
      label1.Text = "The thread was cancelled";
    else
      label1.Text = "The thread was completed normally";

    // Return fCancelled to its initial value
    fCancelled = false;
  }

  ...

}

 


Related topics