내보내기(0) 인쇄
모두 확장

동기 메서드를 비동기 방식으로 호출

.NET Framework에서는 모든 메서드를 비동기 방식으로 호출할 수 있습니다. 이렇게 하려면 호출하려는 메서드와 같은 시그니처를 사용하여 대리자를 정의합니다. 그러면 공용 언어 런타임은 이 대리자에 대해 BeginInvokeEndInvoke 메서드를 해당 시그니처와 함께 자동으로 정의합니다.

BeginInvoke 메서드는 비동기 호출을 시작합니다. 이 메서드의 매개 변수는 비동기 방식으로 실행하려는 메서드의 매개 변수와 같으며, 이 이외에도 두 개의 매개 변수가 더 사용됩니다. 첫 번째 매개 변수는 비동기 호출이 완료될 때 호출될 메서드를 참조하는 AsyncCallback 대리자이고 두 번째 매개 변수는 콜백 메서드에 정보를 전달하는 사용자 정의 개체입니다. BeginInvoke는 비동기 호출이 완료될 때까지 대기하지 않고 즉시 반환합니다. BeginInvoke는 비동기 호출 진행률을 모니터링하는 데 사용할 수 있는 IAsyncResult를 반환합니다.

EndInvoke 메서드는 비동기 호출의 결과를 검색합니다. 이 메서드는 BeginInvoke를 호출한 다음 언제라도 호출할 수 있으며 비동기 호출이 완료되지 않은 경우 EndInvoke가 해당 호출이 완료될 때까지 호출 스레드를 블로킹합니다. EndInvoke의 매개 변수에는 비동기 방식으로 실행하려는 메서드의 outref 매개 변수(Visual Basic의 <Out> ByRefByRef)와 BeginInvoke에 의해 반환되는 IAsyncResult가 있습니다.

Note참고

Visual Studio 2005의 IntelliSense 기능은 BeginInvokeEndInvoke의 매개 변수를 표시합니다. Visual Studio 또는 이와 유사한 도구를 사용하지 않거나 Visual Studio 2005와 C#을 함께 사용하는 경우 이러한 메서드에 대해 정의된 매개 변수에 대한 설명을 보려면 비동기 프로그래밍 개요를 참조하십시오.

이 항목의 코드 예제에서는 BeginInvokeEndInvoke를 사용하여 비동기 호출을 수행하는 네 가지 일반적인 방법을 보여 줍니다. BeginInvoke를 호출한 후 다음과 같은 작업을 수행할 수 있습니다.

  • 일정한 작업을 수행한 다음 EndInvoke를 호출하여 호출이 완료될 때까지 차단합니다.

  • System.IAsyncResult.AsyncWaitHandle 속성을 사용하여 WaitHandle을 가져오고 해당 WaitOne 메서드를 사용하여 WaitHandle이 신호를 받을 때까지 실행을 블로킹한 다음 EndInvoke를 호출합니다.

  • BeginInvoke에 의해 반환된 IAsyncResult를 폴링하여 비동기 호출 완료 시기를 확인한 다음 EndInvoke를 호출합니다.

  • 콜백 메서드의 대리자를 BeginInvoke로 전달합니다. 이 메서드는 비동기 호출이 완료될 때 ThreadPool 스레드에서 실행됩니다. 콜백 메서드가 EndInvoke를 호출합니다.

    Note중요

    항상 EndInvoke를 호출하여 비동기 호출을 완료합니다.

테스트 메서드 및 비동기 대리자 정의

다음에 나오는 코드 예제에서는 장기 실행 메서드 TestMethod를 비동기식으로 호출하는 다양한 방법을 보여 줍니다. TestMethod 메서드는 처리를 시작한 후 몇 초 동안 중지되었다가 종료되었음을 나타내는 콘솔 메시지를 표시합니다. TestMethod에는 BeginInvokeEndInvoke의 시그니처에 매개 변수가 추가되는 방식을 보여 주기 위한 out 매개 변수가 있습니다. ref 매개 변수도 마찬가지로 처리할 수 있습니다.

다음 코드 예제에서는 TestMethod의 정의와 TestMethod를 비동기식으로 호출하는 데 사용할 수 있는 AsyncMethodCaller라는 대리자를 보여 줍니다. 코드 예제를 컴파일하려면 TestMethodAsyncMethodCaller 대리자의 정의를 포함시켜야 합니다.

using System;
using System.Threading; 

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncDemo 
    {
        // The method to be executed asynchronously.
        public string TestMethod(int callDuration, out int threadId) 
        {
            Console.WriteLine("Test method begins.");
            Thread.Sleep(callDuration);
            threadId = Thread.CurrentThread.ManagedThreadId;
            return String.Format("My call time was {0}.", callDuration.ToString());
        }
    }
    // The delegate must have the same signature as the method
    // it will call asynchronously.
    public delegate string AsyncMethodCaller(int callDuration, out int threadId);
}

EndInvoke로 비동기 호출 대기

메서드를 비동기 방식으로 실행하는 가장 간단한 방법은 대리자의 BeginInvoke 메서드를 호출하여 메서드 실행을 시작하고 주 스레드에서 특정 작업을 수행한 다음 대리자의 EndInvoke 메서드를 호출하는 것입니다. EndInvoke는 비동기 호출이 완료될 때까지 반환하지 않으므로 호출 스레드를 블로킹할 수 있습니다. 이 방법은 파일 또는 네트워크 작업에 사용하는 것이 좋지만 이 경우 EndInvoke가 블로킹되므로 사용자 인터페이스를 사용하는 스레드에서는 이 메서드를 호출하지 않아야 합니다.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        public static void Main() 
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
       
            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // Call EndInvoke to wait for the asynchronous call to complete,
            // and to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

WaitHandle로 비동기 호출 대기

BeginInvoke에 의해 반환되는 IAsyncResultAsyncWaitHandle 속성을 사용하여 WaitHandle을 가져올 수 있습니다. 비동기 호출이 완료되면 WaitHandle은 신호를 받으며 WaitOne 메서드를 호출하여 대기할 수 있습니다.

WaitHandle을 사용하는 경우 비동기 호출이 완료되기 전이나 후에, EndInvoke를 호출하여 결과를 검색하기 전에 추가 처리 작업을 수행할 수 있습니다.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() 
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
       
            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            // Perform additional processing here.
            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

비동기 호출 완료에 대한 폴링

BeginInvoke에 의해 반환되는 IAsyncResultIsCompleted 속성을 사용하여 비동기 호출이 완료되는 시기를 알 수 있습니다. 사용자 인터페이스 스레드에서 비동기 호출을 수행하는 경우 이 동작을 수행할 수 있습니다. 완료에 대해 폴링하면 비동기 호출이 ThreadPool 스레드에서 실행되는 동안 호출 스레드가 계속 실행될 수 있습니다.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
       
            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            // Poll while simulating work.
            while(result.IsCompleted == false) {
                Thread.Sleep(10);
            }

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

비동기 호출이 완료될 때 콜백 메서드 실행

비동기 호출을 시작하는 스레드가 결과를 처리하는 스레드일 필요가 없는 경우에는 호출이 완료될 때 콜백 메서드를 실행할 수 있습니다. 콜백 메서드는 ThreadPool 스레드에서 실행됩니다.

콜백 메서드를 사용하려면 BeginInvoke에 해당 메서드를 참조하는 AsyncCallback 대리자를 전달해야 합니다. 또한 콜백 메서드에서 사용하는 정보가 들어 있는 개체를 전달할 수도 있습니다. 예를 들어, 호출을 시작하는 데 사용된 대리자를 전달하면 콜백 메서드에서 EndInvoke를 호출할 수 있습니다.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        // Asynchronous method puts the thread id here.
        private static int threadId;

        static void Main() {
            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
       
            // Initiate the asychronous call.  Include an AsyncCallback
            // delegate representing the callback method, and the data
            // needed to call EndInvoke.
            IAsyncResult result = caller.BeginInvoke(3000,
                out threadId, 
                new AsyncCallback(CallbackMethod),
                caller );

            Console.WriteLine("Press Enter to close application.");
            Console.ReadLine();
        }
        
        // Callback method must have the same signature as the
        // AsyncCallback delegate.
        static void CallbackMethod(IAsyncResult ar) 
        {
            // Retrieve the delegate.
            AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, ar);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

참고 항목

커뮤니티 추가 항목

추가
Microsoft는 MSDN 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 진행하고 있습니다. 참여하도록 선택하시면 MSDN 웹 사이트에서 나가실 때 온라인 설문 조사가 표시됩니다.

참여하시겠습니까?
표시:
© 2014 Microsoft