博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delegate类的BeginInvoke()异步委托方法
阅读量:4043 次
发布时间:2019-05-24

本文共 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属性获取。

你可能感兴趣的文章
No.176 - LeetCode1309
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
mysql:sql alter database修改数据库字符集
查看>>
mysql:sql truncate (清除表数据)
查看>>
yuv to rgb 转换失败呀。天呀。谁来帮帮我呀。
查看>>
yuv420 format
查看>>
YUV420只绘制Y通道
查看>>
yuv420 还原为RGB图像
查看>>
LED恒流驱动芯片
查看>>
驱动TFT要SDRAM做为显示缓存
查看>>
使用file查看可执行文件的平台性,x86 or arm ?
查看>>
qt5 everywhere 编译summary
查看>>
qt5 everywhere编译完成后,找不到qmake
查看>>
qt 创建异形窗体
查看>>
可重入函数与不可重入函数
查看>>
简单Linux C线程池
查看>>
内存池
查看>>
输入设备节点自动生成
查看>>
GNU hello代码分析
查看>>
Qt继电器控制板代码
查看>>