使用异步方式调用同步方法

由于委托是方法的抽象,那么委托可以实现异步调用的话,方法也能实现异步,因此可使用委托实现同步方法的异步调用。

首先定义与要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义BeginInvoke 和 EndInvoke 方法。

BeginInvoke 方法可启动异步调用。它与需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回 IAsyncResult,这个结果可用于监视异步调用进度。

AsyncCallback委托

AsyncCallBack抽象了所有异步方法执行的回调函数(方法),它规定了回调函数(方法)必须拥有一个IAsyncResult的参数并且没有返回值。结束异步操作时调用的回调方法,IAsyncResult作为参数被传递进去,这时IAsyncResult起到了向回调方法传递信息的作用。

IAsyncResult接口

  1. IAsyncResult 接口由包含可异步操作的方法的类实现。它是启动异步操作的方法的返回类型,也是结束异步操作的方法的第三个参数的类型
  2. 当异步操作完成时,IAsyncResult 对象也将传递给由 AsyncCallback 委托调用的方法

EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后,可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括需要异步执行的方法的outref 参数以及由BeginInvoke 返回的IAsyncResult。

调用 BeginInvoke 之后,可以执行下列操作:

  • 进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。

  • 使用 System.IAsyncResult.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne 方法一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。

  • 轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。

  • 将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在ThreadPool 线程上执行该方法,该回调方法将调用 EndInvoke。

具体实例如下:

1.定义要异步调用的同步方法及对应的委托

namespace 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);
}

2.如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法。

在此使用回调方法实现,使用此方法必须将引用回调方法的 AsyncCallback委托传递给BeginInvoke,也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便在回调方法能够调用EndInvoke。

注:BeginInvoke方法的第二个参数就是传入AsyncCallback中的AsyncResult.AsyncState,可以强转成相关的类型加以使用

namespace 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);
        }
    }
}

 上例实现了回调方法来处理异步,实际上,可根据实际情况,对结果做相应的操作(上述说的四种操作中的其一),就写到这里,O(∩_∩)O~~,希望大家多多指教!!!

posted @ 2012-12-20 19:57  Susie_hua  阅读(373)  评论(0编辑  收藏  举报