C# Asynchronous Programming Model - APM
http://msdn.microsoft.com/en-us/library/ms228963.aspx
http://msdn.microsoft.com/ko-kr/library/ms228963.aspx
APM은 BeginMethod <--> EndMethod를 쌍으로 엮여진 메소드로 비동기를 구현하는 모델이다. 이미 .Net frameworkd에서는 파일이나 네트워크 관련으로 메소드를 APM(begin, end) 방식으로 비 동기 메소드를 구현하였다. 아래 그림1에서 확인 할 수 있다.
[그림1] Begin으로 시작하는 메소드
그림1에서와 같이 System.IO와 System.Net 하위 클래스에서 Begin으로 시작하는 메소드가 많으며 이 메소드와 쌍으로 End로 시작하는 메소드가 있을 것이다.
(해당 그림은 Object Browser에서 검색하여 나온 결과 화면이다.)
예제로 파일을 동기와 비 동기로 저장하는 방법을 알아 보도록 하자.
동기식 파일 저장 예제
[TestMethod] public void AsyncUnitTest_APM_Sync() { var contents = "컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용 무수히 많음"; var contentsBytes = Encoding.UTF8.GetBytes(contents); //Temp 파일 얻어 오기 var pathInfo = Path.GetTempFileName(); using (var fileStream = File.OpenWrite(pathInfo)) { // 파일에 쓰기 fileStream.Write(contentsBytes, 0, (int)contentsBytes.Length); fileStream.Flush(); fileStream.Close(); } }
비 동기식 파일 저장 예제
[TestMethod] public void AsyncUnitTest_APM_ASync() { var contents = "컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용, 컨텐츠 내용 무수히 많음"; var contentsBytes = Encoding.UTF8.GetBytes(contents); //Temp 파일 얻어 오기 var pathInfo = Path.GetTempFileName(); var fileStream = File.OpenWrite(pathInfo); // 파일에 쓰기 var result = fileStream.BeginWrite(contentsBytes, 0, contentsBytes.Length, new AsyncCallback(FileStreamReadEnd), fileStream); var handle = result.AsyncWaitHandle; // 완료 될 때까지 대기, 옵션 사항으로 사용함. WaitHandle.WaitAll(new[] { result.AsyncWaitHandle }); //WaitHandle 사용으로 대기는 해당 쓰레드가 완료가 되며 아래 Flow에서 완료된 값이 필요 할 때 대기 할 수 있으나 필요치 않을 때는 대기 하지 않고 넘어 가도 됨 #region WaitHandle에서 완료가 되면 실행 해야 하는 코드 //code #endregion } public void FileStreamReadEnd(IAsyncResult result) { //완료 여부 체크 if (result.IsCompleted) { //넘겨준 파라메터를 해당 object로 변환 var fileStream = (FileStream)result.AsyncState; //완료 표시 fileStream.EndRead(result); fileStream.Flush(); fileStream.Close(); }}
일단 한번 Copy & Paste를 해서 디버깅 모드로 따라가면서 흐름을 익혀 보자.
동기식 실행 : 특별한 설명이 없어도 절차적으로 한번에 하나씩 순차적으로 흐름을 타고 내려가는 것을 확인 할 수 있을 것이다.
비 동기 실행 : BeginWrite를 실행하면 흐름이 두 가지로 나눠지는 것을 확인 할 수 있다.
BeginWrite를 실행하면 본 문맥에서는 result(IAsyncResult)객체를 반환하고 바로 아래 구문을 실행할 것이며 "WhatHandle"에서 IAsyncResult 객체가 완료가 될 때까지 대기하는 흐름이고 또 하나는 AsyncCallback에서 호출되어진 FileStreamReadEnd 메소드가 실행이 될 것이다. FileStreamReadEnd 메소드는 파일 내용을 다 읽었으면 EndRead ( 여기서는 FileStream의 BeginWrite의 쌍이다 )를 실행하여 IAsyncResult 객체에 완료가 되었다는 것을 알려 준다. 그리고 원래 하려고 하였던 Close 작업을 해 주고 완료 한다. 이와 같은 방식으로 파일 읽기를 비 동기로 작업 하였다.
APM 타입 비동기 작업에서 중요한 객체는 IAyncResult다. 이 IAsyncResult 객체를 사용해서 비동기 진행 상태나 완료 상태를 알아 내고 Begin 할때 넘겨준 파라메터 객체를 이용해 특정 객체를 접근할 수 있다. 아래 그림1은 IAsyncResult의 전체적인 flow이다.
[그림1] IAsyncReslt 흐름도
BeginMethod를 실행하면 IAsyncResult 돌려줘서 현재 문맥에서 컨트롤 할 수 있도로 하며(대기 또는 진행 여부 체크 등) AsyncCallbacak에서 정의해준 EndMethod를 실행할 때 파라메터로 IAsyncResult를 넘겨 준다. BeginMethod에서 반환된 IAsyncResult 객체와 EndMethod에서 받은 IAsyncResult 파라메터는 각은 객체다.
IAsyncResult 객체의 흐름과 BeginMethod, EndMethod의 상관관계를 알고 있으면 쉽게 비동기 실행할 수 있을 것이다. 아래는 IAsyncResult 객체의 맴버에 대한 설명이다. (MSDN 발췌)
멤버 | 설명 |
---|---|
비동기 작업에 대한 정보를 포함하는 선택적 응용 프로그램 관련 개체입니다. | |
비동기 작업이 완료될 때까지 응용 프로그램 실행을 블로킹하는 데 사용할 수 있는 WaitHandle입니다. | |
비동기 작업이 별도의 ThreadPool 스레드에서 완료되는 대신 BeginOperationName 호출에 사용된 스레드에서 완료되었는지 여부를 나타내는 값입니다. | |
비동기 작업이 완료되었는지 여부를 나타내는 값입니다. |
'.Net Framework' 카테고리의 다른 글
[C# Async]Event-based Asynchronous Pattern - EAP(2) Async #4 (0) | 2013.02.25 |
---|---|
[C# Async]Event-based Asynchronous Pattern - EAP(1) Async #3 (0) | 2013.02.21 |
[C# Rx] Reactive Programming (0) | 2013.02.18 |
[C# Async] Asynchronous Programming Patterns - Async #1 (0) | 2013.02.18 |
[.Net 4.5] 2Gb 이상 메모리 사용 하기 (0) | 2013.02.18 |