IT_Programming/C#

비동기 방식의 콜백함수 (AsyncCallBack, BeginInvoke(), EndInvoke())

JJun ™ 2009. 7. 8. 17:13

=================================================================================================

 

 산만한 분위기 속에서 개념과 흐름을 제대로 잡는데 꽤나 시간이 걸렸다...

 이와 관련된 크로스 쓰레딩 기법은 대용량 데이터 load와 같은 기능과 Winform Control의 기능을

 분리시켜 안정성을 지킴과 동시에 사용자를 배려한 UI를 제공한다는 면에서 필수적인 것 같다.

 그리고 기타 여러 자료들을 찾다가 느낀점인데.... 개발자가 좀 더 비동기 방식의 프로그래밍을 쉽게 할 수

 있도록 신경 쓴 MS의 배려(?)도 느낄 수 있었다. ( 예제로 만든 소스의 주석은 MSDN의 내용을 참고함 )

 

=================================================================================================

 

[실행화면] 

 

:  메인함수의 기능이 실행되는 동안 제곱을 구하는 함수(squre())는 비동기적으로 수행되어

   출력된 결과 

 

=================================================================================================

 

[소스 코드]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging; // AsyncResult 클래스를 사용하기 위해 추가

 

namespace AsyncCallBackTest
{
    class Program
    {

        // 비동기 방식의 호출을 위해 선언한 delegate (인자가 있으므로 새롭게 정의)
        private delegate int SqureResult(int i);

 

        static void Main(string[] args) // 메인 함수
        {
            SqureResult s = new SqureResult(squre); // 대리자 객체 생성 (함수 등록)

 

            // IAsyncResult 인터페이스를 지원하는 개체는 비동기 작업에 대한 상태 정보를 저장하며,
            // 작업이 완료될 때 스레드에게 신호를 보낼 수 있는 동기화 개체를 제공합니다.


            // AsyncCallback대리자비동기 작업이 완료될 때 호출되는 콜백 메서드를 나타냅니다.
            // 콜백 메서드는 나중에 비동기 작업의 결과를 가져오는 데 사용되는 IAsyncResult 매개 변수를

            // 사용합니다. 


            // ↓ 비동기로 처리할 함수(squre())에 인자로 7을 넘겨주고 수행이 끝나면 콜백함수(resultCheck)

            //    를 호출한다.
            IAsyncResult ar = s.BeginInvoke(7, new AsyncCallback(resultCheck), null);                    

            WaitHandle wh = ar.AsyncWaitHandle; // AsyncWaitHandle - 비동기 작업이 끝나기를

                                                                  //                                 기다리는데 사용되는

                                                                  //                                 WaitHandle을 가져옵니다.
            wh.WaitOne();

 

            // 7의 제곱을 구하는 비동기 함수가 종료될 때까지 메인함수가 할 일 (0~19까지 출력)
            for (int i=0; i<20; ++i)
            {
                Console.WriteLine("Main() : {0}", i);
            }

            wh.Close();
        }

 

        // 비동기로 처리할  함수 호출이 끝났을 때 호출되는 콜백 함수

        static void resultCheck(IAsyncResult ar) 
        {

         // AsyncState - 비동기 작업에 대한 정보를 한정하거나 포함하는 사용자 정의 개체를 가져옵니다.
            int value = Convert.ToInt32(ar.AsyncState);

 

        // AsyncResult 클래스는 비동기 대리자와 함께 사용됩니다. 
        // 대리자의 BeginInvoke 메서드에서 반환되는 IAsyncResult는 AsyncResult로 캐스팅될 수

        // 있습니다. AsyncResult는 비동기 호출이 호출된 대리자 개체를 포함하는 AsyncDelegate 속성을

        // 갖습니다.

 

        // AsyncDelegate - 비동기 호출이 호출된 대리자 개체를 가져옵니다. 
            SqureResult temp = (SqureResult)((AsyncResult)ar).AsyncDelegate;

                   
       // EndInvoke는 호출이 완료될 때까지 호출하는 스레드를 차단
       // 매개변수 : 비동기 방식으로 동작하는 메서드의 out, ref 매개변수 및 BeginInvoke() 메서드의

       //                IAsyncResult
            int result = temp.EndInvoke(ar); // result - 비동기 작업에서 생성된 반환 값을 나타내는 Object.

            Console.WriteLine("\n결과 : {0}({1})\n", result, value); // result - 49, value - 0
        }
       
        static int squre(int i) // 인자로 받은 수의 제곱을 리턴하는 함수 (비동기로 처리할 함수)

        {
            return i * i;
        }
    }
}

 

=================================================================================================