摘要
异步这东西,真正用起来的时候,发现事情还是挺多的,最近在项目中用到了异步的知识,发现对它还是不了解,处理起来,走了不少弯路。觉得还是补一补还是很有必要的。
MSDN原文地址:https://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx
正文
.Net framework可以让你异步调用任何方法。为达这样的目的,你可以定义一个与你要调用的方法的签名相同的委托。公共语言运行时将自动为该委托定义与签名相同的BeginInvok和EndInvoke方法。
异步委托调用BeginInvok和EndInvoke方法,但在.NET Compact Framework中并不支持。
BeginInvoke方法触发你的异步方法,它和你想要执行的异步方法有相同的参数。另外还有两个可选参数,第一个是AsyncCallback委托是异步完成的回调方法。第二个是用户自定义对象,该对象将传递到回调方法中。BeginInvoke立即返回并且不等待完成异步的调用(继续执行该下面的代码,不需要等待)。BeginInvoke返回IAsyncResult接口,可用于检测异步调用的过程。
通过EndInvoke方法检测异步调用的结果。如果异步调用尚未完成,EndInvoke将阻塞调用线程,直到它完成。EndInvoke参数包括out和ref参数。
下面代码演示使用BeginInvoke和EndInvoke进行异步调用的四种常见方式。在调用BeginInvoke可以做以下工作:
- 做一些其他操作,然后调用EndInvoke方法阻塞线程直到该方法完成。
- 使用IAsyncResult.AsyncWaitHandle属性,使用它的WaitOne方法阻塞线程直到收到WaitHandle信号,然后调用EndInvoke。
- 检查BeginInvoke返回值IAsyncResult的状态来决定方法是否完成,然后调用EndInvoke方法。
- 通过在BeginInvoke方法中传递该委托,在回调方法中调用该委托的EenInvoke方法。
注意
无论你怎么使用,都必须调用EndInvoke方法结束你的异步调用。
下面通过模拟一个耗时的操作,实现上面说的那四种情况。
情况一:通过EndInovke阻塞线程,直到异步调用结束。
using System; using System.Diagnostics; using System.Threading; namespace BeginInvokeDemo { /// <summary> /// 委托必须和要调用的异步方法有相同的签名 /// </summary> /// <param name="callDuration">sleep时间</param> /// <param name="threadId">当前线程id</param> /// <returns></returns> public delegate string AsyncMethodCaller(int callDuration, out int threadId); class Program { /// <summary> /// 主函数 /// </summary> /// <param name="args"></param> static void Main(string[] args) { AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync); int threadid = 0; //开启异步操作 IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null); for (int i = 0; i < 10; i++) { Console.WriteLine("其它业务" + i.ToString()); } //调用EndInvoke,等待异步执行完成 Console.WriteLine("等待异步方法TestMethodAsync执行完成"); string res = caller.EndInvoke(out threadid, result); Console.WriteLine("Completed!"); Console.WriteLine(res); Console.Read(); } /// <summary> /// 与委托对应的方法 /// </summary> /// <param name="callDuration"></param> /// <param name="threadId"></param> /// <returns></returns> static string TestMethodAsync(int callDuration, out int threadId) { Stopwatch sw = new Stopwatch();