BackgroundWorker Classe

Definição

Executa uma operação em outro thread.

public ref class BackgroundWorker : IDisposable
public ref class BackgroundWorker : System::ComponentModel::Component
public class BackgroundWorker : IDisposable
public class BackgroundWorker : System.ComponentModel.Component
type BackgroundWorker = class
    interface IDisposable
type BackgroundWorker = class
    inherit Component
Public Class BackgroundWorker
Implements IDisposable
Public Class BackgroundWorker
Inherits Component
Herança
BackgroundWorker
Herança
Implementações

Exemplos

O exemplo de código a BackgroundWorker seguir demonstra os conceitos básicos da classe para executar uma operação demorada de forma assíncrona. A ilustração a seguir mostra um exemplo da saída.

Exemplo simples de BackgroundWorker

Para experimentar esse código, crie um aplicativo Windows Forms. Adicione um Label controle chamado resultLabel e adicione dois Button controles chamados startAsyncButton e cancelAsyncButton. Crie Click manipuladores de eventos para ambos os botões. Na guia Componentes da Caixa de Ferramentas, adicione um BackgroundWorker componente chamado backgroundWorker1. Crie DoWorkmanipuladores de eventos , ProgressChangede RunWorkerCompleted para o BackgroundWorker. No código do formulário, substitua o código existente pelo código a seguir.

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace BackgroundWorkerSimple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        private void startAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void cancelAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker1.CancelAsync();
            }
        }

        // This event handler is where the time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        // This event handler updates the progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
        }

        // This event handler deals with the results of the background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }
    }
}
Imports System.ComponentModel

Public Class Form1

    Public Sub New()
        InitializeComponent()
        backgroundWorker1.WorkerReportsProgress = True
        backgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Sub startAsyncButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles startAsyncButton.Click
        If backgroundWorker1.IsBusy <> True Then
            ' Start the asynchronous operation.
            backgroundWorker1.RunWorkerAsync()
        End If
    End Sub

    Private Sub cancelAsyncButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles cancelAsyncButton.Click
        If backgroundWorker1.WorkerSupportsCancellation = True Then
            ' Cancel the asynchronous operation.
            backgroundWorker1.CancelAsync()
        End If
    End Sub

    ' This event handler is where the time-consuming work is done.
    Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, _
    ByVal e As DoWorkEventArgs) Handles backgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i As Integer

        For i = 1 To 10
            If (worker.CancellationPending = True) Then
                e.Cancel = True
                Exit For
            Else
                ' Perform a time consuming operation and report progress.
                System.Threading.Thread.Sleep(500)
                worker.ReportProgress(i * 10)
            End If
        Next
    End Sub

    ' This event handler updates the progress.
    Private Sub backgroundWorker1_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles backgroundWorker1.ProgressChanged
        resultLabel.Text = (e.ProgressPercentage.ToString() + "%")
    End Sub

    ' This event handler deals with the results of the background operation.
    Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
        If e.Cancelled = True Then
            resultLabel.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            resultLabel.Text = "Error: " & e.Error.Message
        Else
            resultLabel.Text = "Done!"
        End If
    End Sub
End Class

O exemplo de código a seguir demonstra o uso da BackgroundWorker classe para executar uma operação demorada de forma assíncrona. A ilustração a seguir mostra um exemplo da saída.

Exemplo de BackgroundWorker Fibonacci

A operação calcula o número fibonacci selecionado, relata atualizações de progresso à medida que o cálculo prossegue e permite que um cálculo pendente seja cancelado.

#using <System.Drawing.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Threading;
using namespace System::Windows::Forms;

public ref class FibonacciForm: public System::Windows::Forms::Form
{
private:

   int numberToCompute;
   int highestPercentageReached;

   System::Windows::Forms::NumericUpDown^ numericUpDown1;
   System::Windows::Forms::Button^ startAsyncButton;
   System::Windows::Forms::Button^ cancelAsyncButton;
   System::Windows::Forms::ProgressBar^ progressBar1;
   System::Windows::Forms::Label ^ resultLabel;
   System::ComponentModel::BackgroundWorker^ backgroundWorker1;

public:
   FibonacciForm()
   {
      InitializeComponent();
      numberToCompute = highestPercentageReached = 0;
      InitializeBackgoundWorker();
   }


private:

   // Set up the BackgroundWorker object by 
   // attaching event handlers. 
   void InitializeBackgoundWorker()
   {
      backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &FibonacciForm::backgroundWorker1_DoWork );
      backgroundWorker1->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &FibonacciForm::backgroundWorker1_RunWorkerCompleted );
      backgroundWorker1->ProgressChanged += gcnew ProgressChangedEventHandler( this, &FibonacciForm::backgroundWorker1_ProgressChanged );
   }

   void startAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
   {
      
      // Reset the text in the result label.
      resultLabel->Text = String::Empty;

      // Disable the UpDown control until 
      // the asynchronous operation is done.
      this->numericUpDown1->Enabled = false;

      // Disable the Start button until 
      // the asynchronous operation is done.
      this->startAsyncButton->Enabled = false;

      // Enable the Cancel button while 
      // the asynchronous operation runs.
      this->cancelAsyncButton->Enabled = true;

      // Get the value from the UpDown control.
      numberToCompute = (int)numericUpDown1->Value;

      // Reset the variable for percentage tracking.
      highestPercentageReached = 0;

      // Start the asynchronous operation.
      backgroundWorker1->RunWorkerAsync( numberToCompute );
   }

   void cancelAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
   {  
      // Cancel the asynchronous operation.
      this->backgroundWorker1->CancelAsync();
      
      // Disable the Cancel button.
      cancelAsyncButton->Enabled = false;
   }

   // This event handler is where the actual,
   // potentially time-consuming work is done.
   void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
   {
      // Get the BackgroundWorker that raised this event.
      BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);

      // Assign the result of the computation
      // to the Result property of the DoWorkEventArgs
      // object. This is will be available to the 
      // RunWorkerCompleted eventhandler.
      e->Result = ComputeFibonacci( safe_cast<Int32>(e->Argument), worker, e );
   }

   // This event handler deals with the results of the
   // background operation.
   void backgroundWorker1_RunWorkerCompleted( Object^ /*sender*/, RunWorkerCompletedEventArgs^ e )
   {
      // First, handle the case where an exception was thrown.
      if ( e->Error != nullptr )
      {
         MessageBox::Show( e->Error->Message );
      }
      else
      if ( e->Cancelled )
      {
         // Next, handle the case where the user cancelled 
         // the operation.
         // Note that due to a race condition in 
         // the DoWork event handler, the Cancelled
         // flag may not have been set, even though
         // CancelAsync was called.
         resultLabel->Text = "Cancelled";
      }
      else
      {
         // Finally, handle the case where the operation 
         // succeeded.
         resultLabel->Text = e->Result->ToString();
      }

      // Enable the UpDown control.
      this->numericUpDown1->Enabled = true;

      // Enable the Start button.
      startAsyncButton->Enabled = true;

      // Disable the Cancel button.
      cancelAsyncButton->Enabled = false;
   }

   // This event handler updates the progress bar.
   void backgroundWorker1_ProgressChanged( Object^ /*sender*/, ProgressChangedEventArgs^ e )
   {
      this->progressBar1->Value = e->ProgressPercentage;
   }

   // This is the method that does the actual work. For this
   // example, it computes a Fibonacci number and
   // reports progress as it does its work.
   long ComputeFibonacci( int n, BackgroundWorker^ worker, DoWorkEventArgs ^ e )
   {
      // The parameter n must be >= 0 and <= 91.
      // Fib(n), with n > 91, overflows a long.
      if ( (n < 0) || (n > 91) )
      {
         throw gcnew ArgumentException( "value must be >= 0 and <= 91","n" );
      }

      long result = 0;
      
      // Abort the operation if the user has cancelled.
      // Note that a call to CancelAsync may have set 
      // CancellationPending to true just after the
      // last invocation of this method exits, so this 
      // code will not have the opportunity to set the 
      // DoWorkEventArgs.Cancel flag to true. This means
      // that RunWorkerCompletedEventArgs.Cancelled will
      // not be set to true in your RunWorkerCompleted
      // event handler. This is a race condition.
      if ( worker->CancellationPending )
      {
         e->Cancel = true;
      }
      else
      {
         if ( n < 2 )
         {
            result = 1;
         }
         else
         {
            result = ComputeFibonacci( n - 1, worker, e ) + ComputeFibonacci( n - 2, worker, e );
         }

         // Report progress as a percentage of the total task.
         int percentComplete = (int)((float)n / (float)numberToCompute * 100);
         if ( percentComplete > highestPercentageReached )
         {
            highestPercentageReached = percentComplete;
            worker->ReportProgress( percentComplete );
         }
      }

      return result;
   }

   void InitializeComponent()
   {
      this->numericUpDown1 = gcnew System::Windows::Forms::NumericUpDown;
      this->startAsyncButton = gcnew System::Windows::Forms::Button;
      this->cancelAsyncButton = gcnew System::Windows::Forms::Button;
      this->resultLabel = gcnew System::Windows::Forms::Label;
      this->progressBar1 = gcnew System::Windows::Forms::ProgressBar;
      this->backgroundWorker1 = gcnew System::ComponentModel::BackgroundWorker;
      (dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->BeginInit();
      this->SuspendLayout();
      
      // 
      // numericUpDown1
      // 
      this->numericUpDown1->Location = System::Drawing::Point( 16, 16 );
      array<Int32>^temp0 = {91,0,0,0};
      this->numericUpDown1->Maximum = System::Decimal( temp0 );
      array<Int32>^temp1 = {1,0,0,0};
      this->numericUpDown1->Minimum = System::Decimal( temp1 );
      this->numericUpDown1->Name = "numericUpDown1";
      this->numericUpDown1->Size = System::Drawing::Size( 80, 20 );
      this->numericUpDown1->TabIndex = 0;
      array<Int32>^temp2 = {1,0,0,0};
      this->numericUpDown1->Value = System::Decimal( temp2 );

      // 
      // startAsyncButton
      // 
      this->startAsyncButton->Location = System::Drawing::Point( 16, 72 );
      this->startAsyncButton->Name = "startAsyncButton";
      this->startAsyncButton->Size = System::Drawing::Size( 120, 23 );
      this->startAsyncButton->TabIndex = 1;
      this->startAsyncButton->Text = "Start Async";
      this->startAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::startAsyncButton_Click );

      // 
      // cancelAsyncButton
      // 
      this->cancelAsyncButton->Enabled = false;
      this->cancelAsyncButton->Location = System::Drawing::Point( 153, 72 );
      this->cancelAsyncButton->Name = "cancelAsyncButton";
      this->cancelAsyncButton->Size = System::Drawing::Size( 119, 23 );
      this->cancelAsyncButton->TabIndex = 2;
      this->cancelAsyncButton->Text = "Cancel Async";
      this->cancelAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::cancelAsyncButton_Click );

      // 
      // resultLabel
      // 
      this->resultLabel->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
      this->resultLabel->Location = System::Drawing::Point( 112, 16 );
      this->resultLabel->Name = "resultLabel";
      this->resultLabel->Size = System::Drawing::Size( 160, 23 );
      this->resultLabel->TabIndex = 3;
      this->resultLabel->Text = "(no result)";
      this->resultLabel->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

      // 
      // progressBar1
      // 
      this->progressBar1->Location = System::Drawing::Point( 18, 48 );
      this->progressBar1->Name = "progressBar1";
      this->progressBar1->Size = System::Drawing::Size( 256, 8 );
      this->progressBar1->Step = 2;
      this->progressBar1->TabIndex = 4;

      // 
      // backgroundWorker1
      // 
      this->backgroundWorker1->WorkerReportsProgress = true;
      this->backgroundWorker1->WorkerSupportsCancellation = true;

      // 
      // FibonacciForm
      // 
      this->ClientSize = System::Drawing::Size( 292, 118 );
      this->Controls->Add( this->progressBar1 );
      this->Controls->Add( this->resultLabel );
      this->Controls->Add( this->cancelAsyncButton );
      this->Controls->Add( this->startAsyncButton );
      this->Controls->Add( this->numericUpDown1 );
      this->Name = "FibonacciForm";
      this->Text = "Fibonacci Calculator";
      (dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->EndInit();
      this->ResumeLayout( false );
   }
};

[STAThread]
int main()
{
   Application::Run( gcnew FibonacciForm );
}
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace BackgroundWorkerExample
{	
    public class FibonacciForm : System.Windows.Forms.Form
    {	
        private int numberToCompute = 0;
        private int highestPercentageReached = 0;

        private System.Windows.Forms.NumericUpDown numericUpDown1;
        private System.Windows.Forms.Button startAsyncButton;
        private System.Windows.Forms.Button cancelAsyncButton;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Label resultLabel;
        private System.ComponentModel.BackgroundWorker backgroundWorker1;

        public FibonacciForm()
        {	
            InitializeComponent();

            InitializeBackgroundWorker();
        }

        // Set up the BackgroundWorker object by 
        // attaching event handlers. 
        private void InitializeBackgroundWorker()
        {
            backgroundWorker1.DoWork += 
                new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(
            backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.ProgressChanged += 
                new ProgressChangedEventHandler(
            backgroundWorker1_ProgressChanged);
        }
    
        private void startAsyncButton_Click(System.Object sender, 
            System.EventArgs e)
        {
            // Reset the text in the result label.
            resultLabel.Text = String.Empty;

            // Disable the UpDown control until 
            // the asynchronous operation is done.
            this.numericUpDown1.Enabled = false;

            // Disable the Start button until 
            // the asynchronous operation is done.
            this.startAsyncButton.Enabled = false;

            // Enable the Cancel button while 
            // the asynchronous operation runs.
            this.cancelAsyncButton.Enabled = true;

            // Get the value from the UpDown control.
            numberToCompute = (int)numericUpDown1.Value;

            // Reset the variable for percentage tracking.
            highestPercentageReached = 0;

            // Start the asynchronous operation.
            backgroundWorker1.RunWorkerAsync(numberToCompute);
        }

        private void cancelAsyncButton_Click(System.Object sender, 
            System.EventArgs e)
        {   
            // Cancel the asynchronous operation.
            this.backgroundWorker1.CancelAsync();

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // This event handler is where the actual,
        // potentially time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, 
            DoWorkEventArgs e)
        {   
            // Get the BackgroundWorker that raised this event.
            BackgroundWorker worker = sender as BackgroundWorker;

            // Assign the result of the computation
            // to the Result property of the DoWorkEventArgs
            // object. This is will be available to the 
            // RunWorkerCompleted eventhandler.
            e.Result = ComputeFibonacci((int)e.Argument, worker, e);
        }

        // This event handler deals with the results of the
        // background operation.
        private void backgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                // Next, handle the case where the user canceled 
                // the operation.
                // Note that due to a race condition in 
                // the DoWork event handler, the Cancelled
                // flag may not have been set, even though
                // CancelAsync was called.
                resultLabel.Text = "Canceled";
            }
            else
            {
                // Finally, handle the case where the operation 
                // succeeded.
                resultLabel.Text = e.Result.ToString();
            }

            // Enable the UpDown control.
            this.numericUpDown1.Enabled = true;

            // Enable the Start button.
            startAsyncButton.Enabled = true;

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // This event handler updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        // This is the method that does the actual work. For this
        // example, it computes a Fibonacci number and
        // reports progress as it does its work.
        long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
        {
            // The parameter n must be >= 0 and <= 91.
            // Fib(n), with n > 91, overflows a long.
            if ((n < 0) || (n > 91))
            {
                throw new ArgumentException(
                    "value must be >= 0 and <= 91", "n");
            }

            long result = 0;

            // Abort the operation if the user has canceled.
            // Note that a call to CancelAsync may have set 
            // CancellationPending to true just after the
            // last invocation of this method exits, so this 
            // code will not have the opportunity to set the 
            // DoWorkEventArgs.Cancel flag to true. This means
            // that RunWorkerCompletedEventArgs.Cancelled will
            // not be set to true in your RunWorkerCompleted
            // event handler. This is a race condition.

            if (worker.CancellationPending)
            {   
                e.Cancel = true;
            }
            else
            {   
                if (n < 2)
                {   
                    result = 1;
                }
                else
                {   
                    result = ComputeFibonacci(n - 1, worker, e) + 
                             ComputeFibonacci(n - 2, worker, e);
                }

                // Report progress as a percentage of the total task.
                int percentComplete = 
                    (int)((float)n / (float)numberToCompute * 100);
                if (percentComplete > highestPercentageReached)
                {
                    highestPercentageReached = percentComplete;
                    worker.ReportProgress(percentComplete);
                }
            }

            return result;
        }

        #region Windows Form Designer generated code
        
        private void InitializeComponent()
        {
            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
            this.startAsyncButton = new System.Windows.Forms.Button();
            this.cancelAsyncButton = new System.Windows.Forms.Button();
            this.resultLabel = new System.Windows.Forms.Label();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
            this.SuspendLayout();
            // 
            // numericUpDown1
            // 
            this.numericUpDown1.Location = new System.Drawing.Point(16, 16);
            this.numericUpDown1.Maximum = new System.Decimal(new int[] {
            91,
            0,
            0,
            0});
            this.numericUpDown1.Minimum = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            this.numericUpDown1.Name = "numericUpDown1";
            this.numericUpDown1.Size = new System.Drawing.Size(80, 20);
            this.numericUpDown1.TabIndex = 0;
            this.numericUpDown1.Value = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            // 
            // startAsyncButton
            // 
            this.startAsyncButton.Location = new System.Drawing.Point(16, 72);
            this.startAsyncButton.Name = "startAsyncButton";
            this.startAsyncButton.Size = new System.Drawing.Size(120, 23);
            this.startAsyncButton.TabIndex = 1;
            this.startAsyncButton.Text = "Start Async";
            this.startAsyncButton.Click += new System.EventHandler(this.startAsyncButton_Click);
            // 
            // cancelAsyncButton
            // 
            this.cancelAsyncButton.Enabled = false;
            this.cancelAsyncButton.Location = new System.Drawing.Point(153, 72);
            this.cancelAsyncButton.Name = "cancelAsyncButton";
            this.cancelAsyncButton.Size = new System.Drawing.Size(119, 23);
            this.cancelAsyncButton.TabIndex = 2;
            this.cancelAsyncButton.Text = "Cancel Async";
            this.cancelAsyncButton.Click += new System.EventHandler(this.cancelAsyncButton_Click);
            // 
            // resultLabel
            // 
            this.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.resultLabel.Location = new System.Drawing.Point(112, 16);
            this.resultLabel.Name = "resultLabel";
            this.resultLabel.Size = new System.Drawing.Size(160, 23);
            this.resultLabel.TabIndex = 3;
            this.resultLabel.Text = "(no result)";
            this.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(18, 48);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(256, 8);
            this.progressBar1.Step = 2;
            this.progressBar1.TabIndex = 4;
            // 
            // backgroundWorker1
            // 
            this.backgroundWorker1.WorkerReportsProgress = true;
            this.backgroundWorker1.WorkerSupportsCancellation = true;
            // 
            // FibonacciForm
            // 
            this.ClientSize = new System.Drawing.Size(292, 118);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.resultLabel);
            this.Controls.Add(this.cancelAsyncButton);
            this.Controls.Add(this.startAsyncButton);
            this.Controls.Add(this.numericUpDown1);
            this.Name = "FibonacciForm";
            this.Text = "Fibonacci Calculator";
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
            this.ResumeLayout(false);
        }
        #endregion

        [STAThread]
        static void Main()
        {
            Application.Run(new FibonacciForm());
        }
    }
}
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms

Public Class FibonacciForm
    Inherits System.Windows.Forms.Form

    Private numberToCompute As Integer = 0
    Private highestPercentageReached As Integer = 0

    Private numericUpDown1 As System.Windows.Forms.NumericUpDown
    Private WithEvents startAsyncButton As System.Windows.Forms.Button
    Private WithEvents cancelAsyncButton As System.Windows.Forms.Button
    Private progressBar1 As System.Windows.Forms.ProgressBar
    Private resultLabel As System.Windows.Forms.Label
    Private WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker


    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub startAsyncButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles startAsyncButton.Click

        ' Reset the text in the result label.
        resultLabel.Text = [String].Empty

        ' Disable the UpDown control until 
        ' the asynchronous operation is done.
        Me.numericUpDown1.Enabled = False

        ' Disable the Start button until 
        ' the asynchronous operation is done.
        Me.startAsyncButton.Enabled = False

        ' Enable the Cancel button while 
        ' the asynchronous operation runs.
        Me.cancelAsyncButton.Enabled = True

        ' Get the value from the UpDown control.
        numberToCompute = CInt(numericUpDown1.Value)

        ' Reset the variable for percentage tracking.
        highestPercentageReached = 0


        ' Start the asynchronous operation.
        backgroundWorker1.RunWorkerAsync(numberToCompute)
    End Sub 

    Private Sub cancelAsyncButton_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles cancelAsyncButton.Click
        
        ' Cancel the asynchronous operation.
        Me.backgroundWorker1.CancelAsync()

        ' Disable the Cancel button.
        cancelAsyncButton.Enabled = False
        
    End Sub

    ' This event handler is where the actual work is done.
    Private Sub backgroundWorker1_DoWork( _
    ByVal sender As Object, _
    ByVal e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork

        ' Get the BackgroundWorker object that raised this event.
        Dim worker As BackgroundWorker = _
            CType(sender, BackgroundWorker)

        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.
        e.Result = ComputeFibonacci(e.Argument, worker, e)
    End Sub

    ' This event handler deals with the results of the
    ' background operation.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted

        ' First, handle the case where an exception was thrown.
        If (e.Error IsNot Nothing) Then
            MessageBox.Show(e.Error.Message)
        ElseIf e.Cancelled Then
            ' Next, handle the case where the user canceled the 
            ' operation.
            ' Note that due to a race condition in 
            ' the DoWork event handler, the Cancelled
            ' flag may not have been set, even though
            ' CancelAsync was called.
            resultLabel.Text = "Canceled"
        Else
            ' Finally, handle the case where the operation succeeded.
            resultLabel.Text = e.Result.ToString()
        End If

        ' Enable the UpDown control.
        Me.numericUpDown1.Enabled = True

        ' Enable the Start button.
        startAsyncButton.Enabled = True

        ' Disable the Cancel button.
        cancelAsyncButton.Enabled = False
    End Sub

    ' This event handler updates the progress bar.
    Private Sub backgroundWorker1_ProgressChanged( _
    ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
    Handles backgroundWorker1.ProgressChanged

        Me.progressBar1.Value = e.ProgressPercentage

    End Sub

    ' This is the method that does the actual work. For this
    ' example, it computes a Fibonacci number and
    ' reports progress as it does its work.
    Function ComputeFibonacci( _
        ByVal n As Integer, _
        ByVal worker As BackgroundWorker, _
        ByVal e As DoWorkEventArgs) As Long

        ' The parameter n must be >= 0 and <= 91.
        ' Fib(n), with n > 91, overflows a long.
        If n < 0 OrElse n > 91 Then
            Throw New ArgumentException( _
                "value must be >= 0 and <= 91", "n")
        End If

        Dim result As Long = 0

        ' Abort the operation if the user has canceled.
        ' Note that a call to CancelAsync may have set 
        ' CancellationPending to true just after the
        ' last invocation of this method exits, so this 
        ' code will not have the opportunity to set the 
        ' DoWorkEventArgs.Cancel flag to true. This means
        ' that RunWorkerCompletedEventArgs.Cancelled will
        ' not be set to true in your RunWorkerCompleted
        ' event handler. This is a race condition.
        If worker.CancellationPending Then
            e.Cancel = True
        Else
            If n < 2 Then
                result = 1
            Else
                result = ComputeFibonacci(n - 1, worker, e) + _
                         ComputeFibonacci(n - 2, worker, e)
            End If

            ' Report progress as a percentage of the total task.
            Dim percentComplete As Integer = _
                CSng(n) / CSng(numberToCompute) * 100
            If percentComplete > highestPercentageReached Then
                highestPercentageReached = percentComplete
                worker.ReportProgress(percentComplete)
            End If

        End If

        Return result

    End Function


    Private Sub InitializeComponent()
        Me.numericUpDown1 = New System.Windows.Forms.NumericUpDown
        Me.startAsyncButton = New System.Windows.Forms.Button
        Me.cancelAsyncButton = New System.Windows.Forms.Button
        Me.resultLabel = New System.Windows.Forms.Label
        Me.progressBar1 = New System.Windows.Forms.ProgressBar
        Me.backgroundWorker1 = New System.ComponentModel.BackgroundWorker
        CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'numericUpDown1
        '
        Me.numericUpDown1.Location = New System.Drawing.Point(16, 16)
        Me.numericUpDown1.Maximum = New Decimal(New Integer() {91, 0, 0, 0})
        Me.numericUpDown1.Minimum = New Decimal(New Integer() {1, 0, 0, 0})
        Me.numericUpDown1.Name = "numericUpDown1"
        Me.numericUpDown1.Size = New System.Drawing.Size(80, 20)
        Me.numericUpDown1.TabIndex = 0
        Me.numericUpDown1.Value = New Decimal(New Integer() {1, 0, 0, 0})
        '
        'startAsyncButton
        '
        Me.startAsyncButton.Location = New System.Drawing.Point(16, 72)
        Me.startAsyncButton.Name = "startAsyncButton"
        Me.startAsyncButton.Size = New System.Drawing.Size(120, 23)
        Me.startAsyncButton.TabIndex = 1
        Me.startAsyncButton.Text = "Start Async"
        '
        'cancelAsyncButton
        '
        Me.cancelAsyncButton.Enabled = False
        Me.cancelAsyncButton.Location = New System.Drawing.Point(153, 72)
        Me.cancelAsyncButton.Name = "cancelAsyncButton"
        Me.cancelAsyncButton.Size = New System.Drawing.Size(119, 23)
        Me.cancelAsyncButton.TabIndex = 2
        Me.cancelAsyncButton.Text = "Cancel Async"
        '
        'resultLabel
        '
        Me.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.resultLabel.Location = New System.Drawing.Point(112, 16)
        Me.resultLabel.Name = "resultLabel"
        Me.resultLabel.Size = New System.Drawing.Size(160, 23)
        Me.resultLabel.TabIndex = 3
        Me.resultLabel.Text = "(no result)"
        Me.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
        '
        'progressBar1
        '
        Me.progressBar1.Location = New System.Drawing.Point(18, 48)
        Me.progressBar1.Name = "progressBar1"
        Me.progressBar1.Size = New System.Drawing.Size(256, 8)
        Me.progressBar1.TabIndex = 4
        '
        'backgroundWorker1
        '
        Me.backgroundWorker1.WorkerReportsProgress = True
        Me.backgroundWorker1.WorkerSupportsCancellation = True
        '
        'FibonacciForm
        '
        Me.ClientSize = New System.Drawing.Size(292, 118)
        Me.Controls.Add(Me.progressBar1)
        Me.Controls.Add(Me.resultLabel)
        Me.Controls.Add(Me.cancelAsyncButton)
        Me.Controls.Add(Me.startAsyncButton)
        Me.Controls.Add(Me.numericUpDown1)
        Me.Name = "FibonacciForm"
        Me.Text = "Fibonacci Calculator"
        CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

    <STAThread()> _
    Shared Sub Main()
        Application.Run(New FibonacciForm)
    End Sub
End Class

Comentários

A BackgroundWorker classe permite que você execute uma operação em um thread separado e dedicado. Operações demoradas, como downloads e transações de banco de dados, podem fazer com que a interface do usuário pareça ter parado de responder enquanto estão em execução. Quando você deseja uma interface do usuário responsiva e enfrenta longos atrasos associados a essas operações, a BackgroundWorker classe fornece uma solução conveniente.

Para executar uma operação demorada em segundo plano, crie um BackgroundWorker e ouça eventos que relatem o progresso da operação e sinalizem quando a operação for concluída. Você pode criar o BackgroundWorker programaticamente ou arrastá-lo para o formulário na guia Componentes da Caixa de Ferramentas. Se você criar o BackgroundWorker no Windows Forms Designer, ele aparecerá na Bandeja de Componentes e suas propriedades serão exibidas no janela Propriedades.

Para configurar para uma operação em segundo plano, adicione um manipulador de eventos para o DoWork evento. Chame sua operação demorada neste manipulador de eventos. Para iniciar a operação, chame RunWorkerAsync. Para receber notificações de atualizações de progresso, manipule o ProgressChanged evento. Para receber uma notificação quando a operação for concluída, manipule o RunWorkerCompleted evento.

Observação

Você deve ter cuidado para não manipular nenhum objeto de interface do usuário em seu DoWork manipulador de eventos. Em vez disso, comunique-se com a interface do usuário por meio dos ProgressChanged eventos e RunWorkerCompleted .

BackgroundWorker os eventos não são realizados em marshaling entre AppDomain limites. Não use um BackgroundWorker componente para executar operações multithread em mais de um AppDomain.

Se a operação em segundo plano exigir um parâmetro, chame RunWorkerAsync com o parâmetro . Dentro do DoWork manipulador de eventos, você pode extrair o parâmetro da DoWorkEventArgs.Argument propriedade .

Para saber mais sobre BackgroundWorker, consulte Como executar uma operação em segundo plano.

Construtores

BackgroundWorker()

Inicializa uma nova instância da classe BackgroundWorker.

Propriedades

CancellationPending

Obtém um valor que indica se o aplicativo solicitou o cancelamento de uma operação em segundo plano.

CanRaiseEvents

Obtém um valor que indica se o componente pode acionar um evento.

(Herdado de Component)
Container

Obtém o IContainer que contém o Component.

(Herdado de Component)
DesignMode

Obtém um valor que indica se o Component está no modo de design no momento.

(Herdado de Component)
Events

Obtém a lista de manipuladores de eventos que estão anexados a este Component.

(Herdado de Component)
IsBusy

Obtém um valor que indica se o BackgroundWorker está executando uma operação assíncrona.

Site

Obtém ou define o ISite do Component.

(Herdado de Component)
WorkerReportsProgress

Obtém ou define um valor que indica se o BackgroundWorker pode relatar atualizações de progresso.

WorkerSupportsCancellation

Obtém ou define um valor que indica se o BackgroundWorker dá suporte ao cancelamento assíncrono.

Métodos

CancelAsync()

Solicita o cancelamento de uma operação pendente em segundo plano.

CreateObjRef(Type)

Cria um objeto que contém todas as informações relevantes necessárias para gerar um proxy usado para se comunicar com um objeto remoto.

(Herdado de MarshalByRefObject)
Dispose()

Realiza tarefas definidas pelo aplicativo associadas à liberação ou à redefinição de recursos não gerenciados.

Dispose()

Libera todos os recursos usados pelo Component.

(Herdado de Component)
Dispose(Boolean)

Esse método não faz nada.

Dispose(Boolean)

Libera os recursos não gerenciados usados pelo Component e opcionalmente libera os recursos gerenciados.

(Herdado de Component)
Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetHashCode()

Serve como a função de hash padrão.

(Herdado de Object)
GetLifetimeService()
Obsoleto.

Recupera o objeto de serviço de tempo de vida atual que controla a política de ciclo de vida para esta instância.

(Herdado de MarshalByRefObject)
GetService(Type)

Retorna um objeto que representa um serviço fornecido pelo Component ou pelo seu Container.

(Herdado de Component)
GetType()

Obtém o Type da instância atual.

(Herdado de Object)
InitializeLifetimeService()
Obsoleto.

Obtém um objeto de serviço de tempo de vida para controlar a política de tempo de vida para essa instância.

(Herdado de MarshalByRefObject)
MemberwiseClone()

Cria uma cópia superficial do Object atual.

(Herdado de Object)
MemberwiseClone(Boolean)

Cria uma cópia superficial do objeto MarshalByRefObject atual.

(Herdado de MarshalByRefObject)
OnDoWork(DoWorkEventArgs)

Aciona o evento DoWork.

OnProgressChanged(ProgressChangedEventArgs)

Aciona o evento ProgressChanged.

OnRunWorkerCompleted(RunWorkerCompletedEventArgs)

Aciona o evento RunWorkerCompleted.

ReportProgress(Int32)

Aciona o evento ProgressChanged.

ReportProgress(Int32, Object)

Aciona o evento ProgressChanged.

RunWorkerAsync()

Inicia a execução de uma operação em segundo plano.

RunWorkerAsync(Object)

Inicia a execução de uma operação em segundo plano.

ToString()

Retorna uma cadeia de caracteres que representa o objeto atual.

(Herdado de Object)
ToString()

Retorna um String que contém o nome do Component, se houver. Esse método não deve ser substituído.

(Herdado de Component)

Eventos

Disposed

Ocorre quando o componente é disposto por uma chamada ao método Dispose().

(Herdado de Component)
DoWork

Ocorre quando RunWorkerAsync() é chamado.

ProgressChanged

Ocorre quando ReportProgress(Int32) é chamado.

RunWorkerCompleted

Ocorre quando a operação em segundo plano foi concluída, cancelada ou gerou uma exceção.

Aplica-se a

Confira também