다음을 통해 공유


연습: 백그라운드에서 작업 실행

완료하는 데 시간이 많이 걸리는 작업이 있는데 사용자 인터페이스에서 지연이 발생하지 않게 하려면 BackgroundWorker 클래스를 사용하여 다른 스레드에서 작업을 실행합니다.

이 예제에 사용된 코드에 대한 전체 목록을 보려면 방법: 백그라운드에서 작업 실행을 참조하십시오.

참고

표시되는 대화 상자와 메뉴 명령은 활성 설정이나 버전에 따라 도움말에서 설명하는 것과 다를 수 있습니다. 설정을 변경하려면 도구 메뉴에서 설정 가져오기 및 내보내기를 선택합니다. 자세한 내용은 설정에 대한 작업을 참조하십시오.

백그라운드에서 작업을 실행하려면

  1. Windows Forms 디자이너에서 폼을 활성화한 후 도구 상자에 있는 두 개의 Button 컨트롤을 폼으로 끌어 놓은 다음 단추의 Name 및 Text 속성을 다음 표에 따라 설정합니다.

    Button

    Name

    Text

    button1

    startBtn

    시작

    button2

    cancelBtn

    Cancel

  2. 도구 상자를 열고 구성 요소 탭을 클릭한 다음 BackgroundWorker 구성 요소를 끌어서 폼에 놓습니다.

    구성 요소 트레이에 backgroundWorker1 구성 요소가 나타납니다.

  3. 속성 창에서 WorkerSupportsCancellation 속성을 true로 설정합니다.

  4. 속성 창에서 이벤트 단추를 클릭한 다음 DoWorkRunWorkerCompleted 이벤트를 두 번 클릭하여 이벤트 처리기를 만듭니다.

  5. 시간이 많이 걸리는 코드를 DoWork 이벤트 처리기에 삽입합니다.

  6. DoWorkEventArgs 매개 변수의 Argument 속성에서 작업에 필요한 모든 매개 변수를 추출합니다.

  7. 계산 결과를 DoWorkEventArgsResult 속성에 할당합니다.

    이 결과는 RunWorkerCompleted 이벤트 처리기에서 사용할 수 있습니다.

    Private Sub backgroundWorker1_DoWork( _
    sender As Object, e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
    
       ' Do not access the form's BackgroundWorker reference directly.
       ' Instead, use the reference provided by the sender parameter.
       Dim bw As BackgroundWorker = CType( sender, BackgroundWorker )
    
       ' Extract the argument.
       Dim arg As Integer = Fix(e.Argument)
    
       ' Start the time-consuming operation.
       e.Result = TimeConsumingOperation(bw, arg)
    
       ' If the operation was canceled by the user, 
       ' set the DoWorkEventArgs.Cancel property to true.
       If bw.CancellationPending Then
          e.Cancel = True
       End If
    
    End Sub   
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do not access the form's BackgroundWorker reference directly.
        // Instead, use the reference provided by the sender parameter.
        BackgroundWorker bw = sender as BackgroundWorker;
    
        // Extract the argument.
        int arg = (int)e.Argument;
    
        // Start the time-consuming operation.
        e.Result = TimeConsumingOperation(bw, arg);
    
        // If the operation was canceled by the user, 
        // set the DoWorkEventArgs.Cancel property to true.
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
    }
    
  8. 작업 결과를 검색하는 코드를 RunWorkerCompleted 이벤트 처리기에 삽입합니다.

    ' This event handler demonstrates how to interpret 
    ' the outcome of the asynchronous operation implemented
    ' in the DoWork event handler.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    sender As Object, e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted
    
       If e.Cancelled Then
          ' The user canceled the operation.
          MessageBox.Show("Operation was canceled")
       ElseIf (e.Error IsNot Nothing) Then
          ' There was an error during the operation.
          Dim msg As String = String.Format("An error occurred: {0}", e.Error.Message)
          MessageBox.Show(msg)
       Else
          ' The operation completed normally.
          Dim msg As String = String.Format("Result = {0}", e.Result)
          MessageBox.Show(msg)
       End If
    End Sub   
    
    // This event handler demonstrates how to interpret 
    // the outcome of the asynchronous operation implemented
    // in the DoWork event handler.
    private void backgroundWorker1_RunWorkerCompleted(
        object sender, 
        RunWorkerCompletedEventArgs e)
    {   
        if (e.Cancelled)
        {
            // The user canceled the operation.
            MessageBox.Show("Operation was canceled");
        }
        else if (e.Error != null)
        {
            // There was an error during the operation.
            string msg = String.Format("An error occurred: {0}", e.Error.Message);
            MessageBox.Show(msg);
        }
        else
        {
            // The operation completed normally.
            string msg = String.Format("Result = {0}", e.Result);
            MessageBox.Show(msg);
        }
    }
    
  9. TimeConsumingOperation 메서드를 구현합니다.

    ' This method models an operation that may take a long time 
    ' to run. It can be cancelled, it can raise an exception,
    ' or it can exit normally and return a result. These outcomes
    ' are chosen randomly.
    Private Function TimeConsumingOperation( _
    bw As BackgroundWorker, _
    sleepPeriod As Integer) As Integer
    
       Dim result As Integer = 0
    
       Dim rand As New Random()
    
         While Not bw.CancellationPending
             Dim [exit] As Boolean = False
    
             Select Case rand.Next(3)
                 ' Raise an exception.
                 Case 0
                     Throw New Exception("An error condition occurred.")
                     Exit While
    
                     ' Sleep for the number of milliseconds
                     ' specified by the sleepPeriod parameter.
                 Case 1
                     Thread.Sleep(sleepPeriod)
                     Exit While
    
                     ' Exit and return normally.
                 Case 2
                     result = 23
                     [exit] = True
                     Exit While
    
                 Case Else
                     Exit While
             End Select
    
             If [exit] Then
                 Exit While
             End If
         End While
    
       Return result
    End Function
    
    // This method models an operation that may take a long time 
    // to run. It can be cancelled, it can raise an exception,
    // or it can exit normally and return a result. These outcomes
    // are chosen randomly.
    private int TimeConsumingOperation( 
        BackgroundWorker bw, 
        int sleepPeriod )
    {
        int result = 0;
    
        Random rand = new Random();
    
        while (!bw.CancellationPending)
        {
            bool exit = false;
    
            switch (rand.Next(3))
            {
                // Raise an exception.
                case 0:
                {
                    throw new Exception("An error condition occurred.");
                    break;
                }
    
                // Sleep for the number of milliseconds
                // specified by the sleepPeriod parameter.
                case 1:
                {
                    Thread.Sleep(sleepPeriod);
                    break;
                }
    
                // Exit and return normally.
                case 2:
                {
                    result = 23;
                    exit = true;
                    break;
                }
    
                default:
                {
                    break;
                }
            }
    
            if( exit )
            {
                break;
            }
        }
    
        return result;
    }
    
  10. Windows Forms 디자이너에서 startButton을 두 번 클릭하여 Click 이벤트 처리기를 만듭니다.

  11. startButton의 Click 이벤트 처리기에서 RunWorkerAsync 메서드를 호출합니다.

    Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click
        Me.backgroundWorker1.RunWorkerAsync(2000)
    End Sub
    
    private void startBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.RunWorkerAsync(2000);
    }
    
  12. Windows Forms 디자이너에서 cancelButton을 두 번 클릭하여 Click 이벤트 처리기를 만듭니다.

  13. Click 이벤트 처리기에서 cancelButton에 대해 CancelAsync 메서드를 호출합니다.

    Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
    private void cancelBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.CancelAsync();
    }
    
  14. 파일 맨 위에서 System.ComponentModel 및 System.Threading 네임스페이스를 가져옵니다.

    Imports System
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Threading
    Imports System.Windows.Forms
    
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
    
  15. F6 키를 눌러 솔루션을 빌드한 다음 Ctrl+F5를 눌러 디버거 외부에서 응용 프로그램을 실행합니다.

참고

F5 키를 눌러 디버거에서 응용 프로그램을 실행할 경우 TimeConsumingOperation 메서드에서 발생한 예외가 디버거에 의해 catch되어 표시됩니다. 응용 프로그램을 디버거 외부에서 실행하면 BackgroundWorker가 예외를 처리하고 RunWorkerCompletedEventArgsError 속성에 예외를 캐시합니다.

  1. 시작 단추를 클릭하여 비동기 작업을 실행한 다음 취소 단추를 클릭하여 실행 중인 비동기 작업을 중지합니다.

    각 작업의 결과가 MessageBox에 표시됩니다.

다음 단계

참고 항목

작업

방법: 백그라운드 작업을 사용하는 폼 구현

방법: 백그라운드에서 작업 실행

참조

BackgroundWorker

DoWorkEventArgs

기타 리소스

BackgroundWorker 구성 요소