C# BackgroundWorker Tutorial
Using BackgroundWorker
Visual Studio 2008 에서 designer view 의 toolbox 를 보면 BackgroundWorker 콤포넌트가 있다. (.Net 2.0 부터 지원)
Fist step
toolbox 에서 "BackgroundWorker" 를 선택한다. 그러면 윈도우 하단에 Backgroundworker 객체가 생길것이다.
Second step
윈도우 하단 회색 부분에 생성된 Backgroundworker 객체를 선택하면 우측에 Property 창을 볼 수 있다.
Third step
Property 창에서 번개 모양 아이콘을 선택하자 (번개 모양 아이콘은 Microsoft 에서 이벤트들을 위한 아이콘이다.)
Backgroundworker 는 event-driven(이벤트 구동) 방식으로 동작한다. 즉, 이벤트가 발생되면 해당 이벤트에 해당하는 동작을 수행하게 되어있다. 따라서 우리는 Backgroundworker 를 사용하기 위하여 필수적인 이벤트를 만들어야 한다.
Fourth step
4번째 단계는 Backgroundworker 의 이벤트 중에 DoWork 를 더블클릭하여 이벤트 핸들러를 만든다. 이제부터 수동으로 코딩을 해줘야 한다. 즉, DoWork 이벤트를 더블클릭하면 디폴트로 "backgroundWorker1_DoWork" 메소드를 만들게 되고 이 메소드에 실질적인 작업을 구현해주게 된다.
※ 위 UI 작업을 통한 Backgroundworker 생성은 직접 손으로 타이핑하여 구현하는 것 보다 쉽다 (정말?!...)
Adding DoWork
DoWork 의 메소드는 보통의 이벤트 핸들러와 유사하다. C# 코드를 보면 backgroundWorker1_DoWork 메소드를 볼 수 있는데 이 메소드는 DoWork 이벤트를 더블클릭 했을 때 자동으로 생성된 메소드다. 테스트를 위해 Thread.Sleep 커맨들를 넣어 보자. Thread.Sleep 메소드는 Backgroundworker 의 실행을 멈추게 할 것이다. 그러나 전체 CPU를 사용하는 것은 아니다. (cf. C# Sleep Method Pauses Programs - dotnetperls.com)
Properties
다음에 설명은 절대적인 내용은 아니지만 Argument, Result, RunWorkerAsync 메소드를 강조하고 싶다. Backgroundworker 의 property 들은 반드시 어떻게 사용되는지 알 고 있어야 한다. 다음은 코딩할 때 참조할 수 있는 각 property 에 대한 설명이다.
DoWorkEventArgs e
e.Argument 와 e.Result 를 포함하고 있다.
즉, DoWorkEventArgs e 는 e.Argument, e.Result 에 접근하는데 사용되어 진다.
e.Argument
RunWorkerAsync 에 의해서 전달받은 parameter reference 를 얻기 위해서 사용되어 진다.
e.Result
Backgroundworker 처리에 과정을 체크할 수 있다.
backgroundWorker1.RunWorkerAsync (object)
worker 스레드에서 작업 시작을 하기위해 호출되어진다.
Executing code
Backgroundworker 에 argument 와 return value 로 명령들(정보들)을 전달해 줄 수 있다. 다음의 테스트 코드는 argument 를 전달해 주는 방법과 Backgroundworker 를 invoke 시키는 방법, 스레드의 결과를 전달받는 방법을 보여주고 있다.
예제 argument 의 생성
위 코드에서 TestObject 는 예제 객체이다. 아마도 여러분의 프로그램에서는 더 중요하고 복잡한 정보가 담겨질 것이다. 위에선 C# collection initializer 문법이 사용되었다.
어디서든 호출될 수 있다.
여러분의 코드 어디에서든 RunWorkerAsync 를 호출할 수 있다. 예제에선 생성자에서 호출하고 있지만 다른 어디에서든 호출할 수 있다.
Implementation DoWork
여러분이 원하는 로직으로 DoWork 의 메소드를 작성할 수 있다. DoWork 의 메소드(이벤트 핸들러) 에서 구현부와 리턴값으로 DoWorkerEvnetArgs 를 사용하라. 아래의 코드에서는 argument 와 result 를 RunWorkerAsync 호출로 연결시키고 있다. 기억하라!! TestObject 는 RunWorkerAsync 에 파라미터로 전달받은 것이고, e.Argument 로 받게 된다. 또한 반드시 캐스팅 연산을 해주어야 한다.
※ e.Argument 는 항상 RunWorkerAsync 에 의해 background worker 에 전달한 것을 포함하고 있다. 간단히 캐스팅을 통해 원래의 타입으로 변환하여 사용할 수 있다.
또한 DoWork 의 이벤트 핸들러 메소드 안에서 처리한 결과를 e.Result 에 담아 리턴 시키도록 하자!!
Using RunWorkerCompleted
앞서 생성한 backgroundworker1 아이콘을 클릭한 후 우측의 번개 모양 아이콘을 선택하면 이벤트 목록이 나온다. 거기서 RunWorkerCompleted 이벤트를 사용할 수 있다. RunWorkerCompleted 를 더블클릭하자.
backgroundWorker1_RunWorkerCompleted 라고 디폴트로 이벤트 핸들러가 생성된다. 이 메소드에 argument 를 받는 코드를 넣어준다.
Tips
Backgroundworker 는 Windowns Form 안에서 스레드들을 구조적으로 overlay 시킨 것으로 매우 직관적이다.
사용하는 단계를 다시 한번 언급한다면,
First, call RunWorkerAsync with an argument.
Backgroundworker 안의 메소드에 어떠한 argument 라도(null 포함) 전달할 수 있다. 객체 상속 관계에 속한 객체도 전달 가능하다.(다형성)
Second, custom processing is run.
DoWork 의 메소드에서 여러분의 코드를 실행시킬 수 있다.
Third, it finished.
여러분이 작성한 처리가 완료되면, RunWorkerCompleted 가 호출된다. 이 메소드 안에서 스레드에서 처리한 (DoWork 의 메소드 에서 처리한) 결과를 전달받을 수 있다. 이런 방법으로 여러분이 작성한 Backgroundworker 객체는 다른 스레드에 있는 객체를 수정한다.
Summary
위에서 C# 언어를 통해 Backgroundworker 컨트롤(컴포넌트) 를 어떻게 사용하는지 살펴보았다. 일반적으로 여러분은 많은 스레들 사용해야 할 때, ThreadPool 사용을 선호한다. 스레드들이 항상 유용한 것은 아니다.(I/O operation 등등). 멀티 코어 시스템에서 우리는 스레드들의 사용이 필요로 하고, Backgroundworker 의 사용은 훌륭한 선택이 될 것이다.
Backgroundworker 클래스 멤버를 살펴보자
메소드와 프로퍼티, 이벤트들을 연관있는 것끼리 묶어 봤다.
RunWorkerAsync - DoWork
RunWorkerAsync 메소드는 백그라운드 작업을 실행 시키는 메소드다. 즉, 스레드를 시작시킨다.
RunWorkerAsync 메소드가 호출되면 DoWork 이벤트가 발생된다. 따라서 DoWork 이벤트의 이벤트 핸들러에 백그라운드에서 처리할 작업을 정의해주면 된다.
WorkerReportsProgress - ReportProgress - ProgressChanged
1. WorkerReportsProgress 프로퍼티
Backgroundworker 객체가 처리작업에 대한 보고(report)를 할 수 있는지에 대해 설정하거나 얻어온다.
default 값은 false 이다. 이 값을 true 로 설정해야 ProgressChanged 이벤트를 발생시킬 수 있다.
2. ReportProgress 메소드
ProgressChanged 이벤트를 발생 시킨다. 매개변수로 Backgroundworker 객체의 작업 완료 정도를 0 에서 100 까지 값을 갖는 퍼센테이지 값을 전달한다. 또한 object 타입으로 RunWorkerAsync 로 전달한 상태 객체값을 전달한다.
3. ProgressChanged 이벤트
ReportProgress 메소드가 호출되었을 때 발생하는 이벤트 이다.
WorkerSupportsCancellation - RunWorkerCompleted
1. WorkerSupportsCancellation 프로퍼티
Backgroundworker 객체가 스레드 취소 기능을 설정하거나 설정값을 얻는다. default 값은 false 이다. 이 값을 true 로 설정해야 RunWorkerCompleted 이벤트가 발생된다.
2. RunWorkerCompleted 이벤트
스레드의 완료, 취소, 예외가 발생했을 때 발생하는 이벤트 이다. 이 이벤트의 매개변수인 RunWorkerCompletedEventArgs 객체를 통해 작업이 중되 취소되었는지, 예외가 발생했는지 알 수 있다.
CancellationPending
Backgroundworker 스레드를 소유한 응용프로그램에서 스레드에 작업 취소를 요청했는지에 대한 설정값을 얻는다.
ProgressChanged
ReportProgress 메소드의 인자로 전달한 값을 ProgressChangedEventArgs 객체를 통해 사용할 수 있다.
RunWorkerCompleted
RunWorkerCompletedEventArgs 객체를 통해 이벤트 정보를 얻을 수 있다.
Cancelled : 스레드의 취소 요청에 의해 스레드가 취소 되었는지에 대한 bool 값
Error : 스레드의 예외 발생에 의한 스레드가 종료 되었는지에 대한 Exception 타입의 값
Result : 스레드가 정상종료 되었을 때 object 값
BackgroundWorker 스레드의 실행
1. 다른 스레드 즉, BackgroundWorker 스레드에서 실행할 이벤트 처리기를 생성한다. 아래 코드에서는 threadWaitPermit_DoWork 이벤트 핸들러를 생성하였다.
2. 메인 스레드에서 BackgroundWorker 스레드를 실행시키기 위해서 RunWorkerAsync 메소드를 호출한다. RunWorkerAsync 메소드를 호출하면 위에서 DoWork 이벤트에 등록한 이벤트 핸들러가 실행된다.
RunWorkerAsync 메소드 호출 시 전달한 매개변수는 DoWork 이벤트 핸들러의 메소드에서 적절한 형변환을 거쳐 사용할 수 있다. 매개변수 DoWorkerEventArgs 의 Argument 매개변수가 전달받은 매개변수 이다. 또한 결과 값을 Result 프로퍼티에 넣어준다. 보통 Argument 매개변수값을 넣어주면 좋다.
BackgroundWorker 스레드의 취소
BackgroundWorker 스레드를 생성한 스레드에서 BackgroundWorker 스레드의 동작을 취소 시킬 수 있다.
1. BackgroundWorker 의 WorkerSupportsCancellation 프로퍼티값을 true 로 설정한다.
2. BackgroundWorker 의 스레드를 취소 하기 위해 CancelAsync 메소드를 호출한다. 위에서 WorkerSupportsCancellation 프로퍼티값을 true 로 설정하지 않은 채 CancelAsync 메소드를 호출하면 예외가 발생하므로 WorkerSupportsCancellation 프로퍼티값을 검사하는 방어적 코딩을 해준다.
3. BackgroundWorker 스레드 작업을 수행하는 DoWork 이벤트의 이벤트 핸들러에서 CancellationPending 프로퍼티값을 검사한다. CancelAsync() 메소드를 호출하면 CancellationPending 프로퍼티 값이 true 가 된다.
BackgroundWorker 스레드의 작업과정 갱신
보통 스레드의 작업 처리 과정을 메인 스레드(UI스레드)의 프로그레스바를 그려주는 것으로 표시한다. BackgroundWorker 스레드에서 이러한 일반적인 처리 과정을 돕는다.
1. WorkerReportsProgress 프로퍼티값을 true 로 설정한다. 스레드에서 작업 갱신 이벤트(ProgressChanged) 발생시 호출될 이벤트 핸들러를 등록한다.
2. BackgroundWorker 스레드에서 UI 작업을 위해 ReportProgress() 메소드를 호출한다. ProgressChanged 이벤트에 등록된 이벤트 핸들러가 호출된다. ReportProgress 메소드의 매개변수로 사용할 정보값을 넘겨준다.
3. ProgressChanged 이벤트에 등록한 이벤트 핸들러를 구현해준다. 이 이벤트 핸들러에서만 UI 스레드에 접근하여 값을(보통 컨트롤) 변경시켜줄 수 있다. ProgressChangedEventArgs 매개변수에서 ProgressPercentage 프로퍼티값이 ReportProgress 메소드에서 전달한 매개변수값이다.
※ ReportProgress 메소드는 2개의 메소드로 오버로딩되어 있다.
두번째 매개변수의 타입이 Object 타입이므로 사용자가 정의한 특정 정보를 담은 데이터를 넘겨줄 수 있다.
ProgressChangedEventArgs 타입의 멤버를 보면 UserState 프로퍼티를 이용하여 두번째 매개변수로 넘긴 값을 받을 수 있다.
BackgroundWorker 스레드의 종료
BackgroundWorker 스레드 종료 이벤트는 RunWorkerCompleted 이다. 이 이벤트에 이벤트 핸들러를 연결 시키면 스레드 종료 시 연결시킨 이벤트 핸들러가 호출된다. 아래 코드에서는 threadWaitPermit_RunWorkerCompleted 이벤트 핸들러를 연결 시켰다.
BackgroundWorker 스레드에서 스레드가 종료되는 상황(취소, 완료, 예외)에 따른 처리를 RunWorkerCompleted 이벤트 핸들러에서 처리해주면 된다.
Using BackgroundWorker
Visual Studio 2008 에서 designer view 의 toolbox 를 보면 BackgroundWorker 콤포넌트가 있다. (.Net 2.0 부터 지원)
Fist step
toolbox 에서 "BackgroundWorker" 를 선택한다. 그러면 윈도우 하단에 Backgroundworker 객체가 생길것이다.
Second step
윈도우 하단 회색 부분에 생성된 Backgroundworker 객체를 선택하면 우측에 Property 창을 볼 수 있다.
Third step
Property 창에서 번개 모양 아이콘을 선택하자 (번개 모양 아이콘은 Microsoft 에서 이벤트들을 위한 아이콘이다.)
Backgroundworker 는 event-driven(이벤트 구동) 방식으로 동작한다. 즉, 이벤트가 발생되면 해당 이벤트에 해당하는 동작을 수행하게 되어있다. 따라서 우리는 Backgroundworker 를 사용하기 위하여 필수적인 이벤트를 만들어야 한다.
Fourth step
4번째 단계는 Backgroundworker 의 이벤트 중에 DoWork 를 더블클릭하여 이벤트 핸들러를 만든다. 이제부터 수동으로 코딩을 해줘야 한다. 즉, DoWork 이벤트를 더블클릭하면 디폴트로 "backgroundWorker1_DoWork" 메소드를 만들게 되고 이 메소드에 실질적인 작업을 구현해주게 된다.
※ 위 UI 작업을 통한 Backgroundworker 생성은 직접 손으로 타이핑하여 구현하는 것 보다 쉽다 (정말?!...)
Adding DoWork
DoWork 의 메소드는 보통의 이벤트 핸들러와 유사하다. C# 코드를 보면 backgroundWorker1_DoWork 메소드를 볼 수 있는데 이 메소드는 DoWork 이벤트를 더블클릭 했을 때 자동으로 생성된 메소드다. 테스트를 위해 Thread.Sleep 커맨들를 넣어 보자. Thread.Sleep 메소드는 Backgroundworker 의 실행을 멈추게 할 것이다. 그러나 전체 CPU를 사용하는 것은 아니다. (cf. C# Sleep Method Pauses Programs - dotnetperls.com)
Properties
다음에 설명은 절대적인 내용은 아니지만 Argument, Result, RunWorkerAsync 메소드를 강조하고 싶다. Backgroundworker 의 property 들은 반드시 어떻게 사용되는지 알 고 있어야 한다. 다음은 코딩할 때 참조할 수 있는 각 property 에 대한 설명이다.
DoWorkEventArgs e
e.Argument 와 e.Result 를 포함하고 있다.
즉, DoWorkEventArgs e 는 e.Argument, e.Result 에 접근하는데 사용되어 진다.
e.Argument
RunWorkerAsync 에 의해서 전달받은 parameter reference 를 얻기 위해서 사용되어 진다.
e.Result
Backgroundworker 처리에 과정을 체크할 수 있다.
backgroundWorker1.RunWorkerAsync (object)
worker 스레드에서 작업 시작을 하기위해 호출되어진다.
Executing code
Backgroundworker 에 argument 와 return value 로 명령들(정보들)을 전달해 줄 수 있다. 다음의 테스트 코드는 argument 를 전달해 주는 방법과 Backgroundworker 를 invoke 시키는 방법, 스레드의 결과를 전달받는 방법을 보여주고 있다.
예제 argument 의 생성
위 코드에서 TestObject 는 예제 객체이다. 아마도 여러분의 프로그램에서는 더 중요하고 복잡한 정보가 담겨질 것이다. 위에선 C# collection initializer 문법이 사용되었다.
어디서든 호출될 수 있다.
여러분의 코드 어디에서든 RunWorkerAsync 를 호출할 수 있다. 예제에선 생성자에서 호출하고 있지만 다른 어디에서든 호출할 수 있다.
Implementation DoWork
여러분이 원하는 로직으로 DoWork 의 메소드를 작성할 수 있다. DoWork 의 메소드(이벤트 핸들러) 에서 구현부와 리턴값으로 DoWorkerEvnetArgs 를 사용하라. 아래의 코드에서는 argument 와 result 를 RunWorkerAsync 호출로 연결시키고 있다. 기억하라!! TestObject 는 RunWorkerAsync 에 파라미터로 전달받은 것이고, e.Argument 로 받게 된다. 또한 반드시 캐스팅 연산을 해주어야 한다.
※ e.Argument 는 항상 RunWorkerAsync 에 의해 background worker 에 전달한 것을 포함하고 있다. 간단히 캐스팅을 통해 원래의 타입으로 변환하여 사용할 수 있다.
또한 DoWork 의 이벤트 핸들러 메소드 안에서 처리한 결과를 e.Result 에 담아 리턴 시키도록 하자!!
Using RunWorkerCompleted
앞서 생성한 backgroundworker1 아이콘을 클릭한 후 우측의 번개 모양 아이콘을 선택하면 이벤트 목록이 나온다. 거기서 RunWorkerCompleted 이벤트를 사용할 수 있다. RunWorkerCompleted 를 더블클릭하자.
backgroundWorker1_RunWorkerCompleted 라고 디폴트로 이벤트 핸들러가 생성된다. 이 메소드에 argument 를 받는 코드를 넣어준다.
Tips
Backgroundworker 는 Windowns Form 안에서 스레드들을 구조적으로 overlay 시킨 것으로 매우 직관적이다.
사용하는 단계를 다시 한번 언급한다면,
First, call RunWorkerAsync with an argument.
Backgroundworker 안의 메소드에 어떠한 argument 라도(null 포함) 전달할 수 있다. 객체 상속 관계에 속한 객체도 전달 가능하다.(다형성)
Second, custom processing is run.
DoWork 의 메소드에서 여러분의 코드를 실행시킬 수 있다.
Third, it finished.
여러분이 작성한 처리가 완료되면, RunWorkerCompleted 가 호출된다. 이 메소드 안에서 스레드에서 처리한 (DoWork 의 메소드 에서 처리한) 결과를 전달받을 수 있다. 이런 방법으로 여러분이 작성한 Backgroundworker 객체는 다른 스레드에 있는 객체를 수정한다.
Summary
위에서 C# 언어를 통해 Backgroundworker 컨트롤(컴포넌트) 를 어떻게 사용하는지 살펴보았다. 일반적으로 여러분은 많은 스레들 사용해야 할 때, ThreadPool 사용을 선호한다. 스레드들이 항상 유용한 것은 아니다.(I/O operation 등등). 멀티 코어 시스템에서 우리는 스레드들의 사용이 필요로 하고, Backgroundworker 의 사용은 훌륭한 선택이 될 것이다.
Backgroundworker 클래스 멤버를 살펴보자
메소드와 프로퍼티, 이벤트들을 연관있는 것끼리 묶어 봤다.
RunWorkerAsync - DoWork
RunWorkerAsync 메소드는 백그라운드 작업을 실행 시키는 메소드다. 즉, 스레드를 시작시킨다.
RunWorkerAsync 메소드가 호출되면 DoWork 이벤트가 발생된다. 따라서 DoWork 이벤트의 이벤트 핸들러에 백그라운드에서 처리할 작업을 정의해주면 된다.
WorkerReportsProgress - ReportProgress - ProgressChanged
1. WorkerReportsProgress 프로퍼티
Backgroundworker 객체가 처리작업에 대한 보고(report)를 할 수 있는지에 대해 설정하거나 얻어온다.
default 값은 false 이다. 이 값을 true 로 설정해야 ProgressChanged 이벤트를 발생시킬 수 있다.
2. ReportProgress 메소드
ProgressChanged 이벤트를 발생 시킨다. 매개변수로 Backgroundworker 객체의 작업 완료 정도를 0 에서 100 까지 값을 갖는 퍼센테이지 값을 전달한다. 또한 object 타입으로 RunWorkerAsync 로 전달한 상태 객체값을 전달한다.
3. ProgressChanged 이벤트
ReportProgress 메소드가 호출되었을 때 발생하는 이벤트 이다.
WorkerSupportsCancellation - RunWorkerCompleted
1. WorkerSupportsCancellation 프로퍼티
Backgroundworker 객체가 스레드 취소 기능을 설정하거나 설정값을 얻는다. default 값은 false 이다. 이 값을 true 로 설정해야 RunWorkerCompleted 이벤트가 발생된다.
2. RunWorkerCompleted 이벤트
스레드의 완료, 취소, 예외가 발생했을 때 발생하는 이벤트 이다. 이 이벤트의 매개변수인 RunWorkerCompletedEventArgs 객체를 통해 작업이 중되 취소되었는지, 예외가 발생했는지 알 수 있다.
CancellationPending
Backgroundworker 스레드를 소유한 응용프로그램에서 스레드에 작업 취소를 요청했는지에 대한 설정값을 얻는다.
ProgressChanged
ReportProgress 메소드의 인자로 전달한 값을 ProgressChangedEventArgs 객체를 통해 사용할 수 있다.
RunWorkerCompleted
RunWorkerCompletedEventArgs 객체를 통해 이벤트 정보를 얻을 수 있다.
Cancelled : 스레드의 취소 요청에 의해 스레드가 취소 되었는지에 대한 bool 값
Error : 스레드의 예외 발생에 의한 스레드가 종료 되었는지에 대한 Exception 타입의 값
Result : 스레드가 정상종료 되었을 때 object 값
BackgroundWorker 스레드의 실행
1. 다른 스레드 즉, BackgroundWorker 스레드에서 실행할 이벤트 처리기를 생성한다. 아래 코드에서는 threadWaitPermit_DoWork 이벤트 핸들러를 생성하였다.
BackgroundWorker threadWaitPermit = new BackgroundWorker();
threadWaitPermit.DoWork += new System.ComponentModel.DoWorkEventHandler(threadWaitPermit_DoWork);
threadWaitPermit.DoWork += new System.ComponentModel.DoWorkEventHandler(threadWaitPermit_DoWork);
2. 메인 스레드에서 BackgroundWorker 스레드를 실행시키기 위해서 RunWorkerAsync 메소드를 호출한다. RunWorkerAsync 메소드를 호출하면 위에서 DoWork 이벤트에 등록한 이벤트 핸들러가 실행된다.
threadWaitPermit.RunWorkerAsync(_evtArgs);
RunWorkerAsync 메소드 호출 시 전달한 매개변수는 DoWork 이벤트 핸들러의 메소드에서 적절한 형변환을 거쳐 사용할 수 있다. 매개변수 DoWorkerEventArgs 의 Argument 매개변수가 전달받은 매개변수 이다. 또한 결과 값을 Result 프로퍼티에 넣어준다. 보통 Argument 매개변수값을 넣어주면 좋다.
private void threadWaitPermit_DoWork(object sender, DoWorkEventArgs e)
{
CustomEventArgs args = e.Argument as CustomEventArgs;
...
e.Result = args;
}
{
CustomEventArgs args = e.Argument as CustomEventArgs;
...
e.Result = args;
}
BackgroundWorker 스레드의 취소
BackgroundWorker 스레드를 생성한 스레드에서 BackgroundWorker 스레드의 동작을 취소 시킬 수 있다.
1. BackgroundWorker 의 WorkerSupportsCancellation 프로퍼티값을 true 로 설정한다.
threadWaitPermit.WorkerSupportsCancellation = true;
2. BackgroundWorker 의 스레드를 취소 하기 위해 CancelAsync 메소드를 호출한다. 위에서 WorkerSupportsCancellation 프로퍼티값을 true 로 설정하지 않은 채 CancelAsync 메소드를 호출하면 예외가 발생하므로 WorkerSupportsCancellation 프로퍼티값을 검사하는 방어적 코딩을 해준다.
if (threadWaitPermit.WorkerSupportsCancellation)
threadWaitPermit.CancelAsync();
threadWaitPermit.CancelAsync();
3. BackgroundWorker 스레드 작업을 수행하는 DoWork 이벤트의 이벤트 핸들러에서 CancellationPending 프로퍼티값을 검사한다. CancelAsync() 메소드를 호출하면 CancellationPending 프로퍼티 값이 true 가 된다.
private void threadWaitPermit_DoWork(object sender, DoWorkEventArgs e)
{
...
if (threadWaitPermit.CancellationPending)
....
{
...
if (threadWaitPermit.CancellationPending)
....
BackgroundWorker 스레드의 작업과정 갱신
보통 스레드의 작업 처리 과정을 메인 스레드(UI스레드)의 프로그레스바를 그려주는 것으로 표시한다. BackgroundWorker 스레드에서 이러한 일반적인 처리 과정을 돕는다.
1. WorkerReportsProgress 프로퍼티값을 true 로 설정한다. 스레드에서 작업 갱신 이벤트(ProgressChanged) 발생시 호출될 이벤트 핸들러를 등록한다.
threadWaitPermit.WorkerReportsProgress = true;
threadWaitPermit.ProgressChanged += ProgressChangedEventHandler(threadWaitPermit_ProgressChanged);
threadWaitPermit.ProgressChanged += ProgressChangedEventHandler(threadWaitPermit_ProgressChanged);
2. BackgroundWorker 스레드에서 UI 작업을 위해 ReportProgress() 메소드를 호출한다. ProgressChanged 이벤트에 등록된 이벤트 핸들러가 호출된다. ReportProgress 메소드의 매개변수로 사용할 정보값을 넘겨준다.
private void threadWaitPermit_DoWork(object sender, DoWorkEventArgs e)
{
...
BackgroundWorker worker = sender as BackgoundWorker;
worker.ReportProgress(10);
...
{
...
BackgroundWorker worker = sender as BackgoundWorker;
worker.ReportProgress(10);
...
3. ProgressChanged 이벤트에 등록한 이벤트 핸들러를 구현해준다. 이 이벤트 핸들러에서만 UI 스레드에 접근하여 값을(보통 컨트롤) 변경시켜줄 수 있다. ProgressChangedEventArgs 매개변수에서 ProgressPercentage 프로퍼티값이 ReportProgress 메소드에서 전달한 매개변수값이다.
private void threadWaitPermit_DoWork(object sender, ProgressChangedEventArgs e)
{
...
progress1.Value = e.ProgressPercentage;
...
{
...
progress1.Value = e.ProgressPercentage;
...
※ ReportProgress 메소드는 2개의 메소드로 오버로딩되어 있다.
두번째 매개변수의 타입이 Object 타입이므로 사용자가 정의한 특정 정보를 담은 데이터를 넘겨줄 수 있다.
ProgressChangedEventArgs 타입의 멤버를 보면 UserState 프로퍼티를 이용하여 두번째 매개변수로 넘긴 값을 받을 수 있다.
BackgroundWorker 스레드의 종료
BackgroundWorker 스레드 종료 이벤트는 RunWorkerCompleted 이다. 이 이벤트에 이벤트 핸들러를 연결 시키면 스레드 종료 시 연결시킨 이벤트 핸들러가 호출된다. 아래 코드에서는 threadWaitPermit_RunWorkerCompleted 이벤트 핸들러를 연결 시켰다.
threadWaitPermit.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(threadWaitPermit_RunWorkerCompleted);
BackgroundWorker 스레드에서 스레드가 종료되는 상황(취소, 완료, 예외)에 따른 처리를 RunWorkerCompleted 이벤트 핸들러에서 처리해주면 된다.
private void threadWaitPermit_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 스레드 작업에서 예외가 발생하여 종료된 경우
if (e.Error != null)
...
// 스레드 작업에서 취소 명령이 발생한 경우
// 스레드에서 e.Cancelled 프로퍼티에 값을 설정해 줄 수 있다.
if (e.Cancelled)
...
{
// 스레드 작업에서 예외가 발생하여 종료된 경우
if (e.Error != null)
...
// 스레드 작업에서 취소 명령이 발생한 경우
// 스레드에서 e.Cancelled 프로퍼티에 값을 설정해 줄 수 있다.
if (e.Cancelled)
...