使用异步方式调用同步方法
由于委托是方法的抽象,那么委托可以实现异步调用的话,方法也能实现异步,因此可使用委托实现同步方法的异步调用。
首先定义与要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法可启动异步调用。它与需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回 IAsyncResult,这个结果可用于监视异步调用进度。
AsyncCallback委托
AsyncCallBack抽象了所有异步方法执行的回调函数(方法),它规定了回调函数(方法)必须拥有一个IAsyncResult的参数并且没有返回值。结束异步操作时调用的回调方法,IAsyncResult作为参数被传递进去,这时IAsyncResult起到了向回调方法传递信息的作用。
IAsyncResult接口
- IAsyncResult 接口由包含可异步操作的方法的类实现。它是启动异步操作的方法的返回类型,也是结束异步操作的方法的第三个参数的类型
- 当异步操作完成时,IAsyncResult 对象也将传递给由 AsyncCallback 委托调用的方法
EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后,可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括需要异步执行的方法的out 和ref 参数以及由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~~,希望大家多多指教!!!