我们已经知道 C#当中 存在async/await 、BackGroudWorker类以及TPL(任务并行库)。当然C#还有一些旧的模式来支持异步编程。参考《C#图解教程》

 1. BeginInovke和EndInvoke简单介绍

 1 delegate long MyDel(int first, int second);
 2
 3 class Program
 4 {
 5     static long Sum(int x, int y)
 6     {
 7         Console.WriteLine("------Inside Sum@{0}", DateTime.Now.ToString());
 8         Thread.Sleep(2000);
 9         return x + y;
10     }
11
12     static void Main(string[] args)
13     {
14         MyDel del = new MyDel(Sum);
15
16         Console.WriteLine("Before BeginInvoke---@{0}", DateTime.Now.ToString());
17         IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
18         Console.WriteLine("After BeginInvoke@{0}", DateTime.Now.ToString());
19
20         Console.WriteLine("Doing stuff@{0}", DateTime.Now.ToString());
21
22         long result = del.EndInvoke(iar);
23         Console.WriteLine("End Invoke@{0}", DateTime.Now.ToString());
24
25         Console.WriteLine("After EndInvoke:  {0}", result);
26
27         Console.ReadKey();
28
29     }
30 }

如上代码,定义了一个委托 MyDel ,并且在调用的时候把Sum方法传给了它的对象。一般情况下我们调用这个委托对象,它就会调用他调用列表中包含的方法。就想调用方法一样,这是同步完成的。

但是如果委托对象在调用列表中只有一个方法(引用方法),它就可以异步的去执行这个方法。BeginInovke和EndInvoke就是用来做这个事的。我们可以用如下的方式使用:

①当我们调用BeginInvoke方法的时候,他开始在一个独立的线程上执行引用方法,并且立即返回到原始线程。原始线程可以继续,而引用方法会在想吃的线程中并行执行。

②当程序希望获取已完成的异步方法的结果时,可以检查BeginInvoke返回的IAsyncResult的IsCompleted属性,或者调用委托的EndInvoke方法来等待委托执行完成。

上面的使用过程就引出的三种模式:

①等待-直到完成 原始线程在发起了异步方法以及做了一些其他处理之后,原始线程就中断并且等待异步方法执行完成之后再继续。

②轮询 ,原始线程定期检查发起的线程是否完成,如果没有则可以继续做其他的事情,

③回调 原始线程一直执行,无需等待或者检查发起的线程是否完成,发起的线程中的引用发放完成之后,发起的线程会调用回调方法,由回调方法在调用的EndInvoke之前处理异步方法的结果。

2.BeginInovke和EndInvoke详细

对于 BeginInvoke 方法,有几个注意的地方

① 我们可以根据上面的代码知道,BeginInvoke的参数包含如下两个部分

l  引用方法的参数

l  CallBack参数和State参数

②BeginInvoke 会在线程池中找到一个线程,让引用方法运行在该线程上

③BeginInvoke 返回给调用线程一个实现IAsyncResult接口的对象的引用。这个接口引用包含了在线程池线程中运行的异步方法的状态。可以判断这个状态来确定异步方法是否结束。

 // 3和5是引用方法参数,两个null分别是Callback参数和State参数// iar是新线程的信息IAsyncResult iar = del.BeginInvoke(3, 5, null, null);

对于 EndInvoke 方法,有几个注意的地方

①他的参数是上面BegionInvoke返回的IAsyncResult接口的引用对象,传入这个对象是便于EndInvoke去找到引用方法运行的线程。并且这个参数置于参数列表最后一个。EndInvoke提供了从异步方法调用的所有输出,包括ref和out参数。如果委托的引用方法有ref和out参数,他们必须包含在EndInvoke的参数列表当中

IAsyncResult iar2 = del2.BeginInvoke(3, 5, out res, null, null);
del2.EndInvoke(out res, iar2); 

②如果线程已经退出了,EndInvoke会做如下事情:

  清理退出的线程的状态并且释放资源

  找到引用方法的返回值,并作为自己的返回值

③如果EndInovke发现线程还在运行中,那么调用线程就会停止并等待,直到清理完毕并返回值。

④因为EndInvoke会去清理线程信息,所以BeginInvoke和EndInvoke必须成对使用。

⑤如果异步方法出现异常,那么在调用EndInvoke的时候会抛出异常。

3.AsyncResult类

上面说BeginInvoke方法返回了一个IAsyncResult接口的引用对象(内部是AsyncResult类的对象),AsyncResult类型表现了异步方法的状态。下面是这类的主要组成部分:

4.三种模式

① 等待-直到完成 (比较简单的模式)

//开始执行异步方法
IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
//Do Something 耗时
del2.EndInvoke(iar);

像上面的代码,BeginInvoke之后,做了一些事情,然后调用EndInvoke来处理结果,这种方式就是等待-直到完成的模式。

②轮询模式

轮询模式中,原始的线程发起了异步的方法调用,做一些事情,然后使用IAsyncResult中的IsComplete熟悉来定期检查开启的线程是否完成。如果未完成就在去做一些其他事情。

delegate long MyDel(int first, int second);class Program
{static long Sum(int x, int y){Console.WriteLine("--Inside Sum@{0}", DateTime.Now.ToString());Thread.Sleep(200);return x + y;}static void Main(string[] args){MyDel del = new MyDel(Sum);//开始执行异步方法IAsyncResult iar = del.BeginInvoke(3, 5, null, null);//轮询开始while (!iar.IsCompleted){//未完成,执行下面的语句for (long i = 0; i < 20000000; i++);}//执行完成调用EndInvoke获取结果long result = del.EndInvoke(iar);Console.ReadKey();}

③回调模式

前两种都是主动方式的,原始线程一直在监控这新开启的线程。但是回调是被动的,一旦原始线程发起了异步方法,它就自己管自己了,不在考虑同步。

当异步方法调用结束之后,系统调用一个用户自定义的方法来处理结果,并且调用委托的EndInvoke方法。这个用户自定义的方法就是回调方法。

上面的BegionInvoke中写过,他会有两个参数一个Callback参数和一个State参数.

CallBack参数:是回调方法的名称。

State参数:可以是null,或者传入回调方法的一个对象的引用。我们可以用IAsyncResult参数的AsyncState属性来获取这个对象,参数的类型是object。

a.回调方法:

回调方法的签名和返回类型必须和 AsyncCallback委托类型所描述的形式一致。

两种方式,构建这个AsyncCallback参数

new AsyncCallback 对象  

IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone),null);

直接传回调方法的名称

IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, null);

其中 CallWhenDone 如下:

static void CallWhenDone(IAsyncResult iar)
{AsyncResult ar = (AsyncResult)iar;MyDel del = (MyDel)ar.AsyncDelegate;//回调方法中调用了EndInvokelong result = del.EndInvoke(iar);
}

b.在回调方法中调用EndInvoke

上面代码中,在回调中使用了EndInvoke,上文中说到 EndInvoke的调用,是委托的调用,并且需要传入一个IAsyncResult的接口对象的引用。

所以想要在回调方法里面,调用这个EndInvoke,就得拿到两个东西一个是委托对象、一个是IAsyncResult,由于我们AsyncCallback委托本身就是必须要传入IAsyncResult 的,所以这个比较容易,剩下的就是委托对象本身了。在AsyncResult类小节里面我看到,它里面存着一个 AsyncDelegate(它就是委托对象的引用),还有就是 IAsyncResult接口对象在内部就是AsyncResult类对象。所以才可以像上main的代码,通过强制类型转换得到MyDel的对象。

第二种方法就是如果State参数没有用处,可以通过State参数,把委托的对象传过去。

调用的地方,最后一个参数传入del

IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone),del);

回调方法:

static void CallWhenDone(IAsyncResult iar)
{MyDel del = (MyDel)iar.AsyncState;long result = del.EndInvoke(iar);
}

转载于:https://www.cnblogs.com/dcz2015/p/11011507.html

C#当中的BeginInvoke和EndInvoke相关推荐

  1. 异步使用委托delegate --- BeginInvoke和EndInvoke方法

    当我们定义一个委托的时候,一般语言运行时会自动帮委托定义BeginInvoke 和 EndInvoke两个方法,这两个方法的作用是可以异步调用委托. 方法BeginInvoke有两个参数: Async ...

  2. C#线程系列讲座(1):BeginInvoke和EndInvoke方法

    本文是转载,原文地址:http://www.itpub.net/thread-1021075-1-1.html 几个关键词:IAsyncResult,isComplete,asyncResult.As ...

  3. BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题

    BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 参考文章: (1)BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 (2)https://www. ...

  4. Invoke and BeginInvoke BeginInvoke和EndInvoke方法 (转)2

    七.其他组件的BeginXXX和EndXXX方法 在其他的.net组件中也有类似BeginInvoke和EndInvoke的方法,如System.Net.HttpWebRequest类的BeginGe ...

  5. Invoke and BeginInvoke BeginInvoke和EndInvoke方法 (转)

      http://www.cnblogs.com/renhaojie/archive/2009/09/10/1564052.html http://www.cnblogs.com/worldreaso ...

  6. 异步编程中的BeginInvoke和EndInvoke

    如果委托对象的调用列表中只有一个方法(引用方法),就可以异步执行这个方法,通过调用委托类特有的两个方法BeginInvoke和EndInvoke去执行. BeginInvoke和EndInvoke 的 ...

  7. C# BeginInvoke与EndInvoke的使用

    之前,我已经说过了BeginInvoke与Invoke的异同 这里就要再来说说endinvoke的意思了 我们知道 beginvoke就是通过线程的调用来异步的完成一些工作.一般只需要启动它就好,让它 ...

  8. 委托的BeginInvoke和EndInvoke

    刚刚搞明白了C#的异步调用,写下来,方便后续调用. 异步主要是解决UI假死的问题,而开辟出一个新的线程,处理大数据. 1.既然是委托的调用,那么先定义个委托: public delegate bool ...

  9. Mcad学习笔记之异步编程(AsyncCallback委托,IAsyncResult接口,BeginInvoke方法,EndInvoke方法的使用小总结)...

    收藏地址  http://aierong.cnblogs.com/archive/2005/05/25/162308.html 让我们来看看同步异步的区别: 同步方法调用在程序继续执行之前需要等待同步 ...

最新文章

  1. php addall,ThinkPHP3.2框架使用addAll()批量插入数据的方法
  2. DataParallel 笔记
  3. Flask之flask-session
  4. 华为杯数学建模优秀论文_数学建模经典例题(2016年国赛B题与优秀论文)
  5. 计算机图形学笔记 (第一周)
  6. 实现textbox输入时模糊查询
  7. EclipseLink+H2 快速搭建JPA开发环境
  8. scala---中的一些string方法
  9. 小琪不小气 - 微信自带表情符号的默认代码
  10. 神经网络基础学习笔记汇总
  11. Mac下安装keras
  12. abaqus截面惯性矩_Abaqus基本概念汇总
  13. iPhone模拟器里面模拟两个手指做放大缩小的手势
  14. linux中ls命令查看文件大小与时间
  15. 【智能制造】生产异常情况的处理流程
  16. 深度学习行人重识别综述与展望,TPAMI 2021 最新文章
  17. 普通人要赚钱,真的需要换一换方法了
  18. App Clips 的配置及链接处理
  19. flinkSql中自定义时间窗口开启时间
  20. echarts做企业关系图谱_echarts交叉关系图一

热门文章

  1. fpga硬件驱动TFT液晶屏-小结
  2. 作为Leader如何与团队成员更好地沟通?
  3. Memcached深度分析【zz】
  4. Customization larbin
  5. Telerik for Winform 2010版下载、安装、初次使用
  6. Entity Framework 代码模板
  7. 使用tag标签是SEO优化的重要性是什么?
  8. 单页面与多页面的区别与优缺点?
  9. 《区块链100问》笔记整理——23~41问
  10. [学习笔记]03.字符串的扩展