本文共 3226 字,大约阅读时间需要 10 分钟。
微软docs参考:
https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/calling-synchronous-methods-asynchronously 也可参考:http://www.cnblogs.com/sosowjb/archive/2012/08/11/2633953.html 写得也很好.异步委托:异步委托就是定义一个方法,开一个新线程,让这个方法在后台执行.这个线程是线程池里的线程,是属于后台线程的。
Delegate类提供了BeginInvoke()异步委托方法,如果是非常耗时的异步操作,那麼在未结束时调用Delegate.EndInvoke()会一直处在阻塞状态。可通過以下3種方法判斷是否完成。
1)BeginInvoke()返回一个IAsyncResult接口,这个接口包含了该委托的相关信息,并且可以通过它的用IsCompleted属性来判断该委托是否执行完成。
2) 等待句柄(AsyncWaitHandle属性) 3) 异步回调(AsyncCallBack委托)—推薦下面是将要异步调用的方法:模拟 n 毫秒后执行完毕.
1: static string DelegateMethod(int ms) 2: { Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId);//标记线程ID 3: Console.WriteLine("Takes started"); 4: Thread.Sleep(ms); 5: Console.WriteLine("Takes completed"); 6: return "Done!"; 7: }
**方法1:用IsCompleted属性判断是否完成。**如果没完成则继续等待,如果完成则跳出循环。用EndInvoke方法获取委托的返回值。如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用的方法执行完毕。
主线程的方法:
首先定义一个委托:public delegate string MyDelegate(int ms); 1: static void Main() 2: { Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示主线程ID 3: MyDelegate dl = DelegateMethod; 4: 5: IAsyncResult ar = dl.BeginInvoke(5000, null, null); --5000是委托方法DelegateMethod的参数,另两个参数是默认的 6: 7: while (!ar.IsCompleted) 8: { 9: Console.Write("waiting"); 10: Thread.Sleep(50); 11: } 12: string result = dl.EndInvoke(ar); -- 13: Console.WriteLine("result: {0}", result); 14: }
委托线程将执行5秒钟,主线程不停的循环判断委托线程是否完成(用IsCompleted属性判断)。如果没完成则继续等待,如果完成则跳出循环。用EndInvoke方法获取委托的返回值。如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用的方法执行完毕。
方法2:等待句柄(AsyncWaitHandle属性)
使用IAsyncResult的AsyncWaitHandle属性可以访问等待句柄,这个属性返回一个WaitHandle对象,这个对象的WaitOne()方法可输入一个超时时间作为参数,设置等待的最长时间。如果超时,WaitOne()方法返回一个bool值,true为等待成功(即委托完成),异步调用的方法与上面一样,
主线程实现:1: static void Main() 2: { 3: MyDelegate dl = DelegateMethod; 4: 5: IAsyncResult ar = dl.BeginInvoke(5000, null, null); 6: while (true) 7: { 8: Console.Write("waiting"); 9: if (ar.AsyncWaitHandle.WaitOne(50)) 10: { 11: Console.WriteLine("Can get the result now"); 12: break; 13: } 14: } 15: string result = dl.EndInvoke(ar); 16: Console.WriteLine("result: {0}", result); 17: }
主线程每等待50秒做一次判断是否完成。
方法3:异步回调(AsyncCallBack委托)–個人推薦這種方法,不會阻塞后面的語句
BeginInvoke方法第二个参数可传入一个AsnycCallBack委托类型的方法,当异步调用完成时会执行这个方法。可以用Lambda表达式或函數来实现:MyDelegate dl = null; static void Main() { dl = DelegateMethod; dl.BeginInvoke(5000, new AsyncCallback(ar => { //異步方法執行完成后執行以下代碼: string result = dl.EndInvoke(ar); Console.WriteLine("result: {0}", result); }), null); // 回調函數獨立封裝 // dl.BeginInvoke(5000, MyCallBack, null); // 此處后面不發生阻塞 for (int i = 0; i < 100; i++) { Console.Write("waiting"); Thread.Sleep(50); } }//回調函數private void MyCallBack(IAsyncResult ar) { string result = dl.EndInvoke(ar); Console.WriteLine("result: {0}", result); }
BeginInvoke方法的最后一个参数可以用IAsyncResult的AsyncState属性获取。