C# Event-based Asynchronous Pattern - EAP (1)
이벤트 기반 비동기 프로그래밍 패턴
http://msdn.microsoft.com/en-us/library/ms228969.aspx
이벤트 기반 비동기 패턴은 APM에서 문제(dead lock, cancellation)가 될 수 있는 사항을 피할 수 있습니다. 이 패턴을 지원하는 가이드로 개발하면 다음 작업을 수월히 수행할 수 있습니다. ( - 이벤트 기반 비동기 프로그래밍은 UI가 있는 어플리케이션에서 주로 사용한다. 라이브러리가 제공되는 Async 메소드를 실행하면 Completed나 Changed 이벤트를 받아서 후속 작업을 처리하면 된다. WinForm이나 WPF에서 많이 사용 한다. - EAP를 사용 해야 할 때 - )
다운로드와 데이터베이스 작업 등 시간이 많이 걸리는 작업을 중단하지 않고 "백그라운드에서" 수행
여러 작업을 동시에 실행하며 각 작업이 완료될 때 알림을 받음
응용 프로그램을 중지하지 않고 리소스를 사용할 수 있을 때까지 대기
익숙한 이벤트 및 대리자 모델을 사용하여 보류 중인 비동기 작업과 통신
이벤트 기반 비동기 패턴은 MethodAsync, MethodCompleted, MethodCancel로 제공되며 이 메소드로 각 작업을 수행하며 위 사항을 지원 한다. 우선 예제를 통해 눈으로 확인을 해봐야 대략적으로 알 수 있을 것이다. 아래 예제를 보도록 하자.
BackgroundWorker bw = new BackgroundWorker(); //RunWorkerAsync() 메소드가 실행되 면 비동기로 실행 될 코드 bw.DoWork += bw_DoWork; //완료시 처리할 이벤트 핸들로 bw.RunWorkerCompleted += bw_RunWorkerCompleted; //상태가 변경되면 처리할 이벤트 핸들로 //통상적으로 진행율을 표시하는 걸로 사용 한다. bw.ProgressChanged += bw_ProgressChanged; //비동기로 메소드 실행 bw.RunWorkerAsync(); //비동기 작업을 취소 할 때 사용 한다. //bw.CancelAsync();
[코드 1] 비동 메소드 사용 예제
BackgroundWorker 클래스는 일반적인 사항에서 비동기적으로 처리할 일을 대신 맡아서 처리하는 클래스다 일반적인 케이스에서는 이 클래스를 사용해서 비 동기 작업을 진행하면 무리가 없을 것이다. 이 클래스는 Winform, ASP.NET, WPF에서 효과적으로 동작 한다.
EAP를 제공하는 라이브러리를 위와 같이 사용하며 전체 소스는 아래와 같다.
/// <summary> /// 진행율 표시 /// </summary> private int inc; /// <summary> /// 이벤트 기반 비동기 테스트 /// </summary> [TestMethod] public void BackgroundWorker_EAP_ASync() { BackgroundWorker bw = new BackgroundWorker(); //RunWorkerAsync() 메소드가 실행되 면 비동기로 실행 될 코드 bw.DoWork += bw_DoWork; //완료시 처리할 이벤트 핸들로 bw.RunWorkerCompleted += bw_RunWorkerCompleted; //상태가 변경되면 처리할 이벤트 핸들로 //통상적으로 진행율을 표시하는 걸로 사용 한다. bw.ProgressChanged += bw_ProgressChanged; //진행상황을 보고 하도록 서정 함(ProgressChanged 이벤트가 동작 한다) bw.WorkerReportsProgress = true;
//비동기로 메소드 실행 bw.RunWorkerAsync(); do{ //비동기가 끝날때까지 대기 if (bw.IsBusy) { Thread.Sleep(1000); } else {
//비동기 작업이 종료되면 loop 밖으로 나간다. break; } } while (true);
//비동기 작업을 취소 할 때 사용 한다. //bw.CancelAsync(); Assert.AreEqual(inc, 100); } /// <summary> /// 백그라운드의 상태가 변경되었을 때 상태값을 파라메터로 넘겨 받아 처리 한다. /// </summary> /// <param name="sender">BackgroundWorker</param> /// <param name="e">ProgressChangedEventArgs</param> void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { int progress = e.ProgressPercentage; //진행율을 표기 한다. } /// <summary> /// 비동기로 실제 작업을 수행하는 코드 /// </summary> /// <param name="sender">BackgroundWorker</param> /// <param name="e">DoWorkEventArgs</param> void bw_DoWork(object sender, DoWorkEventArgs e) { inc = 0; BackgroundWorker worker = (BackgroundWorker)sender; do { //취소 여부를 체크 if (worker.CancellationPending) { e.Cancel = true; //취소로 상태 변경 break; //loop out } else { inc++; worker.ReportProgress(inc); } Thread.Sleep(100); } while (!e.Cancel && inc < 100); //취소 신호가 있으면 바로 나간다, 완료되면 out } /// <summary> /// 비 동기 작업수행이 완료가 되면 실행 된다. /// </summary> /// <param name="sender">BackgroundWorker</param> /// <param name="e">RunWorkerCompletedEventArgs</param> void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { //취소 메세지를 처리 한다. Console.WriteLine("취소 됨"); } else { //완료에 해당하는 작업을 수행한다. Console.WriteLine("정상적으로 완료"); } }
EAP 방식은 위에 나타난 소스 말고도 이벤트 핸들러에 필수 적인 EventsArgs를 상속받은 객체를 세가지 더 구현해야 하는 불편함이 있다. 라이브러리를 사용하는 프로그래머는 어렵지 않게 제공되는 형식의 이벤트대로 구현을 하면 되지만 라이브러리를 만드는 프로그래머는 신경을 써야 하는 부분도 많다. 그렇지만 추상적인 흐름을 만들어 두어 그 안에서 비동기를 지원하도록 하기 때문에 사용자가 쉽게 접근하여 비동기 프로그래밍을 할 수 있도록 강제 또는 가이드를 할 수 있는 이점이 있다.
위 케이스는 하나의 객체에서 여러번의 일을 비동기로 수행할 수 있는 방안은 아니며 "userState" 객체를 이용해서 여러번 수행 할 수 있도록 구분할 수 있는 매커니즘을 구현해야 한다.
다음 포스트에서는 EAP 라이브러리를 만드는 작업에 대해서 알아 보도록 하겠다.
'.Net Framework' 카테고리의 다른 글
[C# Async]Event-based Asynchronous Pattern - EAP(3) Async #5 (0) | 2013.02.25 |
---|---|
[C# Async]Event-based Asynchronous Pattern - EAP(2) Async #4 (0) | 2013.02.25 |
[C# Async]Asynchronous Programming Model - APM Async #2 (0) | 2013.02.21 |
[C# Rx] Reactive Programming (0) | 2013.02.18 |
[C# Async] Asynchronous Programming Patterns - Async #1 (0) | 2013.02.18 |