본문 바로가기
c#

[c#] BeginInvoke사용법 및 예제 -2-(비동기 리턴값)

by devjh 2020. 9. 7.
반응형

개요

1. Thread

2. lock

3. BeginInvoke(비동기, 스레드풀)

4. BeginInvoke2(비동기 리턴값)

5. BeginInvoke3(콜백)

6. BeginInvoke4(BeginInvoke예제)

 


 

저번게시글에서 BeginInvoke의 사용법에 대해 알아보았습니다.

 

비동기작업은 스레드를 직접 생성하는것과는 다르게 스레드풀에서 돌아간다는 차이가 있긴 하지만

 

저번게시글의 작업은 스레드를 하나 더 만들어서 하는것과 큰 차이점을 찾을 수 없었습니다.

 

이번 게시글에서는 스레드의 작업과 비동기작업의 차이점에 대해 살펴보겠습니다.

 

비동기와 스레드 모두 여러개의 작업을 할 수 있지만

 

비동기작업은 스레드와 다르게 리턴값을 받아올 수 있으며, 콜백이라는 구문이 존재합니다.

 

이번 게시글에서는 비동기작업의 리턴값을 받아오는 예제를 만들어 보았습니다.

 

1. 예제

비동기작업으로 1부터 n까지의 합을 구하는 예제입니다.

 

namespace BeginInvokeTest2
{
    delegate int myDelegate(int n);
    class Program
    {
        static void Main(string[] args)
        {
            myDelegate a = Func;
            int cnt = 10;
            Console.WriteLine("1부터 {0}까지 더하고 다 더하면 결과를 말해주세요", cnt);

            // 첫번째 매개변수는 비동기작업에 전달하는 매개변수입니다.
            IAsyncResult ar = a.BeginInvoke(cnt,null,null);
            
            // EndInvoke를 사용하면 비동기 구문의 리턴값을 받아올 수 있습니다.
            // 리턴값을 받으려면 당연히 메인스레드는 해당 비동기작업이 끝날때까지 블락되지만
            // msdn에서는 반환값이 있던 없던 AsyncWaitHandle.WaitOne()을 사용하여 블락시킬것을 권장합니다.
            // WaitOne사용법은 다음게시글에 첨부하겠습니다.
            Console.WriteLine("더할때까지 기다리고 있겠습니다.");
            int result = a.EndInvoke(ar);

            Console.WriteLine("1부터 {0}까지의 합은 {1}이군요.", cnt, result);
        }

        private static int Func(int n)
        {
            int sum = 0;
            for (int i = 1; i <= n; i++)
            {
                sum += i;
                Thread.Sleep(100);
            }
            Console.WriteLine(sum);
            return sum;
        }
    }
}

 

 

비동기작업을 실행할때 좌항에 들어가는 값은 IAsyncResult 타입입니다.

 

비동기작업의 리턴값이 나올꺼라고 착각하기 쉬운데 EndInvoke를 사용해야 비동기 리턴값을 받아올 수 있습니다.

 

리턴값이 나오려면 비동기작업이 끝나야하므로(위의 예제에서는 1초)

 

비동기작업을 호출했던 스레드는 1초동안 아래구문에서 블락되게 됩니다.

int result = a.EndInvoke(ar);

 

정상적인 방법은 WaitOne을 사용하는것이지만

 

결과가 나올때까지 기다리게해서 블락시킬 수도 있구나 정도로 알고가시면 될것 같습니다.

 

WaitOne 사용법은 다음게시글에 첨부하겠습니다.

 

끝.

반응형

댓글