C# 异步编程 结束异步调用

在使用 BeginInvoke 和 EndInvoke 进行异步调用时,调用 BeginInvoke 之后,可以执行下列操作来结束异步调用:

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

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

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

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

 

异步委托

下面的代码演示异步调用同一个长时间运行的方法 TestMethod 的各种方式。TestMethod 方法会显示一条控制台消息,说明它已开始处理,休眠了几秒钟,然后结束。TestMethod 有一个 out 参数,该参数用于演示此种参数添加到 BeginInvoke 和 EndInvoke 的签名中的方式。可以按同样的方式处理 ref 参数。

TestMethod 的定义和名为 AsyncMethodCaller 的、可用来异步调用 TestMethod 的委托。若要编译任何代码示例,必须包括 TestMethod 的定义和 AsyncMethodCaller 委托。

 

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 返回的 IAsyncResult 的 AsyncWaitHandle 属性来获取 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 返回的 IAsyncResult 的 IsCompleted 属性来发现异步调用何时完成。从用户界面的服务线程中进行异步调用时可以执行此操作。轮询完成允许调用线程在异步调用在 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 线程上执行。

若要使用回调方法,必须将引用回调方法的 AsyncCallback 委托传递给 BeginInvoke。也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便回调方法能够调用 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);

        }

    }

}





你可能感兴趣的:(异步调用)