Delegate类的BeginInvoke()异步委托方法

微软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属性获取。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值