연습: 백그라운드에서 작업 실행
완료하는 데 오랜 시간이 걸리는 작업이 있으며 사용자 인터페이스에서 지연이 발생되지 않게 하려는 경우 BackgroundWorker 클래스를 사용하여 다른 스레드에서 작업을 실행할 수 있습니다.
이 예제에서 사용된 코드의 전체 목록은 방법: 백그라운드에서 작업 실행을 참조하세요.
백그라운드에서 작업 실행
Visual Studio의 Windows Forms 디자이너에서 활성 상태인 양식을 사용하여 두 개의 Button 컨트롤을 도구 상자에서 양식으로 끌어온 다음, 다음 표에 따라 단추의
Name
및 Text 속성을 설정합니다.단추 Name 텍스트 button1
startBtn
시작 button2
cancelBtn
취소 도구 상자를 열고, 구성 요소 탭을 클릭한 다음, BackgroundWorker 구성 요소를 양식으로 끌어옵니다.
backgroundWorker1
구성 요소가 구성 요소 트레이에 표시됩니다.속성 창에서 WorkerSupportsCancellation 속성을
true
로 설정합니다.속성 창에서 이벤트 단추를 클릭한 다음, DoWork 및 RunWorkerCompleted 이벤트를 두 번 클릭하여 이벤트 처리기를 만듭니다.
시간이 오래 걸리는 코드를 DoWork 이벤트 처리기에 삽입합니다.
DoWorkEventArgs 매개 변수의 Argument 속성에서 작업에 필요한 매개 변수를 추출합니다.
계산 결과를 DoWorkEventArgs의 Result 속성에 할당합니다.
이는 RunWorkerCompleted 이벤트 처리기에 사용할 수 있습니다.
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; } }
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
RunWorkerCompleted 이벤트 처리기에서 작업 결과를 검색하기 위한 코드를 삽입합니다.
// 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); } }
' 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
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 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; }
' 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
Windows Forms 디자이너에서
startButton
을 두 번 클릭하여 Click 이벤트 처리기를 만듭니다.startButton
에 대한 Click 이벤트 처리기에서 RunWorkerAsync 메서드를 호출합니다.private void startBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.RunWorkerAsync(2000); }
Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click Me.backgroundWorker1.RunWorkerAsync(2000) End Sub
Windows Forms 디자이너에서
startButton
을 두 번 클릭하여 Click 이벤트 처리기를 만듭니다.startButton
에 대한 Click 이벤트 처리기에서 RunWorkerAsync 메서드를 호출합니다.private void cancelBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.CancelAsync(); }
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click Me.backgroundWorker1.CancelAsync() End Sub
파일 맨 위에서 System.ComponentModel 및 System.Threading 네임스페이스를 가져옵니다.
using System; using System.ComponentModel; using System.Drawing; using System.Threading; using System.Windows.Forms;
Imports System.ComponentModel Imports System.Drawing Imports System.Threading Imports System.Windows.Forms
F6 키를 눌러 솔루션을 빌드한 다음, Ctrl+F5를 눌러 디버거 외부에서 애플리케이션을 실행합니다.
참고
F5 키를 눌러 디버거에서 애플리케이션을 실행하는 경우
TimeConsumingOperation
메서드에서 발생한 예외는 디버거에 의해 catch되고 표시됩니다. 디버거 외부에서 애플리케이션을 실행하는 경우 BackgroundWorker는 예외를 처리하고 RunWorkerCompletedEventArgs의 Error 속성에 캐시합니다.시작 단추를 클릭하여 비동기 작업을 실행한 다음, 취소 단추를 클릭하여 실행 중인 비동기 작업을 중지합니다.
각 작업의 결과가 MessageBox에 표시됩니다.
다음 단계
비동기 작업이 진행됨에 따라 진행 상황을 보고하는 양식을 구현합니다. 자세한 내용은 방법: 백그라운드 작업을 사용하는 양식 구현을 참조하세요.
구성 요소에 대한 비동기 패턴을 지원하는 클래스를 구현합니다. 자세한 내용은 이벤트 기반 비동기 패턴 구현을 참조하세요.
참고 항목
.NET Desktop feedback