다음을 통해 공유


BackgroundWorker 클래스

정의

별도의 스레드에서 작업을 실행합니다.

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
상속
BackgroundWorker
상속
구현

예제

다음 코드 예제에서는 시간이 많이 걸리는 작업을 비동기적으로 실행하기 위한 클래스의 BackgroundWorker 기본 사항을 보여 줍니다. 다음 그림에서는 출력의 예를 보여 줍니다.

BackgroundWorker 간단한 예제

이 코드를 시도하려면 Windows Forms 애플리케이션을 만듭니다. 명명된 컨트롤을 Label 추가하고 명명 resultLabelstartAsyncButton 된 두 개의 Button 컨트롤을 추가합니다cancelAsyncButton. 두 단추 모두에 대한 이벤트 처리기를 만듭니 Click 다. 도구 상자의 구성 요소 탭에서 라는 backgroundWorker1구성 요소를 추가 BackgroundWorker 합니다. 에 대한 BackgroundWorker, ProgressChangedRunWorkerCompleted 이벤트 처리기를 만듭니DoWork다. 양식의 코드에서 기존 코드를 다음 코드로 바꿉다.

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;
    }

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

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

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

        for (int i = 1; i <= 10; i++)
        {
            if (worker.CancellationPending)
            {
                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.
    void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) =>
        resultLabel.Text = e.ProgressPercentage.ToString() + "%";

    // This event handler deals with the results of the background operation.
    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) =>
        resultLabel.Text = e.Cancelled ?
        "Canceled!"
        : e.Error != null ? "Error: " + e.Error.Message : "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 Not backgroundWorker1.IsBusy 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 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) 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 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

다음 코드 예제에서는 비동기적으로 시간이 많이 걸리는 작업을 실행 하는 클래스를 BackgroundWorker 사용 하는 방법을 보여 줍니다. 다음 그림에서는 출력의 예를 보여 줍니다.

BackgroundWorker 피보나치 예제

이 작업은 선택한 피보나치 번호를 계산하고, 계산이 진행됨에 따라 진행률 업데이트를 보고하고, 보류 중인 계산을 취소할 수 있도록 허용합니다.

#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.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace BackgroundWorkerExample;

public class FibonacciForm : Form
{
    int numberToCompute;
    int highestPercentageReached;

    NumericUpDown numericUpDown1;
    Button startAsyncButton;
    Button cancelAsyncButton;
    ProgressBar progressBar1;
    Label resultLabel;
    BackgroundWorker backgroundWorker1;

    public FibonacciForm()
    {
        InitializeComponent();

        InitializeBackgroundWorker();
    }

    // Set up the BackgroundWorker object by 
    // attaching event handlers. 
    void InitializeBackgroundWorker()
    {
        backgroundWorker1.DoWork +=
             backgroundWorker1_DoWork;
        backgroundWorker1.RunWorkerCompleted +=

        backgroundWorker1_RunWorkerCompleted;
        backgroundWorker1.ProgressChanged +=

        backgroundWorker1_ProgressChanged;
    }

    void startAsyncButton_Click(object sender,
        EventArgs e)
    {
        // Reset the text in the result label.
        resultLabel.Text = string.Empty;

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

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

        // Enable the Cancel button while 
        // the asynchronous operation runs.
        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(object sender,
        EventArgs e)
    {
        // Cancel the asynchronous operation.
        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 = 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.
    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.
        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) => 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 is < 0 or > 91)
        {
            throw new ArgumentException(
                "value must be >= 0 and <= 91", nameof(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
        {
            result = n < 2
                ? 1
                : ComputeFibonacci(n - 1, worker, e) +
                         ComputeFibonacci(n - 2, worker, e);

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

        return result;
    }

    #region Windows Form Designer generated code

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

    [STAThread]
    static void Main() => Application.Run(new FibonacciForm());
}
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class FibonacciForm
    Inherits Form

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

    Private numericUpDown1 As NumericUpDown
    Private WithEvents startAsyncButton As Button
    Private WithEvents cancelAsyncButton As Button
    Private progressBar1 As ProgressBar
    Private resultLabel As 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.
        numericUpDown1.Enabled = False

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

        ' Enable the Cancel button while 
        ' the asynchronous operation runs.
        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.
        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.
        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

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

    End Sub

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

설명

클래스 BackgroundWorker 를 사용하면 별도의 전용 스레드에서 작업을 실행할 수 있습니다. 다운로드 및 데이터베이스 트랜잭션과 같은 시간이 많이 걸리는 작업으로 인해 UI(사용자 인터페이스)가 실행되는 동안 응답을 중지한 것처럼 보일 수 있습니다. 반응형 UI를 원하고 이러한 작업과 관련된 긴 지연에 직면한 경우 클래스는 BackgroundWorker 편리한 솔루션을 제공합니다.

백그라운드 BackgroundWorker 에서 시간이 많이 걸리는 작업을 실행하려면 작업 진행률을 보고하고 작업이 완료되면 신호를 수신 대기합니다. 프로그래밍 방식으로 만들거나 도구 상자BackgroundWorker구성 요소 탭에서 폼으로 끌어다 놓을 수 있습니다. Windows Forms 디자이너에서 만든 BackgroundWorker 경우 구성 요소 트레이에 해당 속성이 속성 창에 표시됩니다.

백그라운드 작업을 설정하려면 이벤트에 대한 이벤트 처리기를 추가합니다 DoWork . 이 이벤트 처리기에서 시간이 많이 걸리는 작업을 호출합니다. 작업을 시작하려면 .를 호출합니다 RunWorkerAsync. 진행률 업데이트 알림을 받으려면 이벤트를 처리합니다 ProgressChanged . 작업이 완료될 때 알림을 받으려면 이벤트를 처리합니다 RunWorkerCompleted .

메모

이벤트 처리기에서 사용자 인터페이스 개체를 조작하지 않도록 주의해야 합니다 DoWork . 대신, 이벤트 및 이벤트를 통해 사용자 인터페이스와 RunWorkerCompleted 통신합니다ProgressChanged.

BackgroundWorker 이벤트는 경계를 넘어 AppDomain 마샬링되지 않습니다. 구성 요소를 사용하여 BackgroundWorkerAppDomain이상의 다중 스레드 작업을 수행하지 마세요.

백그라운드 작업에 매개 변수가 필요한 경우 매개 변수를 사용하여 호출 RunWorkerAsync 합니다. DoWork 이벤트 처리기 내에서 속성에서 매개 변수를 추출할 DoWorkEventArgs.Argument 수 있습니다.

자세한 BackgroundWorker내용은 방법: 백그라운드에서 작업 실행을 참조하세요.

생성자

Name Description
BackgroundWorker()

BackgroundWorker 클래스의 새 인스턴스를 초기화합니다.

속성

Name Description
CancellationPending

애플리케이션이 백그라운드 작업의 취소를 요청했는지 여부를 나타내는 값을 가져옵니다.

CanRaiseEvents

구성 요소가 이벤트를 발생시키는지 여부를 나타내는 값을 가져옵니다.

(다음에서 상속됨 Component)
Container

IContainer 포함하는 값을 가져옵니다 Component.

(다음에서 상속됨 Component)
DesignMode

현재 디자인 모드인지 여부를 Component 나타내는 값을 가져옵니다.

(다음에서 상속됨 Component)
Events

Component에 연결된 이벤트 처리기 목록을 가져옵니다.

(다음에서 상속됨 Component)
IsBusy

비동기 작업을 실행하고 있는지 여부를 BackgroundWorker 나타내는 값을 가져옵니다.

Site

ISite값을 Component 가져오거나 설정합니다.

(다음에서 상속됨 Component)
WorkerReportsProgress

진행률 업데이트를 보고할 수 있는지 여부를 BackgroundWorker 나타내는 값을 가져오거나 설정합니다.

WorkerSupportsCancellation

비동기 취소를 지원하는지 여부를 BackgroundWorker 나타내는 값을 가져오거나 설정합니다.

메서드

Name Description
CancelAsync()

보류 중인 백그라운드 작업의 취소를 요청합니다.

CreateObjRef(Type)

원격 개체와 통신하는 데 사용되는 프록시를 생성하는 데 필요한 모든 관련 정보를 포함하는 개체를 만듭니다.

(다음에서 상속됨 MarshalByRefObject)
Dispose()

관리되지 않는 리소스의 해제, 해제 또는 재설정과 관련된 애플리케이션 정의 작업을 수행합니다.

Dispose()

에서 사용하는 모든 리소스를 Component해제합니다.

(다음에서 상속됨 Component)
Dispose(Boolean)

이 메서드는 아무 작업도 수행하지 않습니다.

Dispose(Boolean)

관리되지 않는 리소스를 Component 해제하고 관리되는 리소스를 선택적으로 해제합니다.

(다음에서 상속됨 Component)
Equals(Object)

지정된 개체가 현재 개체와 같은지 여부를 확인합니다.

(다음에서 상속됨 Object)
GetHashCode()

기본 해시 함수로 사용됩니다.

(다음에서 상속됨 Object)
GetLifetimeService()
사용되지 않음.

이 인스턴스의 수명 정책을 제어하는 현재 수명 서비스 개체를 검색합니다.

(다음에서 상속됨 MarshalByRefObject)
GetService(Type)

또는 해당 서비스에서 제공하는 서비스를 나타내는 개체를 Component 반환합니다 Container.

(다음에서 상속됨 Component)
GetType()

현재 인스턴스의 Type 가져옵니다.

(다음에서 상속됨 Object)
InitializeLifetimeService()
사용되지 않음.

이 인스턴스의 수명 정책을 제어하는 수명 서비스 개체를 가져옵니다.

(다음에서 상속됨 MarshalByRefObject)
MemberwiseClone()

현재 Object단순 복사본을 만듭니다.

(다음에서 상속됨 Object)
MemberwiseClone(Boolean)

현재 MarshalByRefObject 개체의 단순 복사본을 만듭니다.

(다음에서 상속됨 MarshalByRefObject)
OnDoWork(DoWorkEventArgs)

DoWork 이벤트를 발생시킵니다.

OnProgressChanged(ProgressChangedEventArgs)

ProgressChanged 이벤트를 발생시킵니다.

OnRunWorkerCompleted(RunWorkerCompletedEventArgs)

RunWorkerCompleted 이벤트를 발생시킵니다.

ReportProgress(Int32, Object)

ProgressChanged 이벤트를 발생시킵니다.

ReportProgress(Int32)

ProgressChanged 이벤트를 발생시킵니다.

RunWorkerAsync()

백그라운드 작업의 실행을 시작합니다.

RunWorkerAsync(Object)

백그라운드 작업의 실행을 시작합니다.

ToString()

현재 개체를 나타내는 문자열을 반환합니다.

(다음에서 상속됨 Object)
ToString()

String(있는 경우)의 Component이름을 포함하는 값을 반환합니다. 이 메서드는 재정의해서는 안 됩니다.

(다음에서 상속됨 Component)

이벤트

Name Description
Disposed

구성 요소가 메서드 호출에 Dispose() 의해 삭제될 때 발생합니다.

(다음에서 상속됨 Component)
DoWork

호출할 때 RunWorkerAsync() 발생합니다.

ProgressChanged

호출할 때 ReportProgress(Int32) 발생합니다.

RunWorkerCompleted

백그라운드 작업이 완료되었거나 취소되었거나 예외가 발생할 때 발생합니다.

적용 대상

추가 정보