怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法。委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用。

异步有三种模式

  1. 等待模式,在发起了异步方法以及做了一些其它处理之后,原始线程就中断,并且等待异步方法完成之后再继续。
  2. 轮询模式,原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其它的事情。
  3. 回调模式,原始线程一直在执行,无需等待或检查发起的线程是否完成。在发起的线程中的引用方法完成之后,发起的线程就会调用回调方法,由回调方法在调用EndInvoke之前处理异步方法的结构。

在学习异步编程之前,先看看BeginInvoke和EndInvoke方法。

BeginInvoke方法

  1. 在调用BeginInvoke时,参数列表中的实参组成如下:

    1)  引用方法需要的参数。

    2)  两个额外的参数——callback参数和state参数。

  1. BeginInvoke从线程池中获取一个线程并且在新的线程开始时运行引用方法。
  2. BeginInvoke返回给调用线程一个实现IasyncResult接口的对象。这个接口引用包含了异步方法的当前状态,原始线程然后可以继续执行。

EndInvoke方法

  1. 它接受一个由BeginInvoke方法返回的IasyncResult对象的引用,并找到它关联的线程。
  2. 如果线程池的线程已经退出,EndInvoke做如下的事情。

    1)  它清理退出线程的状态并且释放它的资源。

    2)  它找到引用方法返回的值并且把它的值作为返回值。

  1. 如果当EndInvoke被调用时线程池的线程仍然在运行,调用线程就会停止并等待,直到清理完毕并返回值。因为EndInvoke是为开启的线程进行清理,所以必须确保对每一个BeginInvoke都调用EndInvoke。
  2. 如果异步方法触发了异常,在调用EndInvoke时会抛出异常。

等待模式

在这种模式里,原始线程发起一个异步方法的调用,做一些其它处理,然后停止并等待,直到开启的线程结束。如下图

这段代码产生了如下输出。

  既然我们已经看到了BeginInvoke和EndInoke的最简单形式,可以进一步了解IasyncResult了,它是使用这些方法的必要部分。

BeginInvoke返回一个IasyncResult接口的引用(内部是AsyncResult类的对象)。AsyncResult类表现了异步方法的状态。如下图:

  1. 当我们调用委托对象的BeginInvoke方法时,系统创建了一个AsyncResult类的对象。然而,它不返回类的对象的引用,而是返回对象中包含的IasyncResult接口的引用。
  2. AsyncResult对象包含一个叫做AsyncDelegate的属性,它返回一个指向被调用来开启异步方法的委托的引用。但是这个属性是类对象的一部分而是接口的一部分。
  3. IsCompleted属性返回一个布尔值,表示异步方法是否完成。
  4. AsyncState属性返回一个对象的引用,它被作为BeginInvoke方法调用时的state参数。它返回object类型的引用,稍后再讲解。。

轮询模式

  在轮询模式中,原始线程发起了异步方法的调用,做一些其它处理,然后使用IAsyncResult对象的IsCompleted属性来定期检查开启的线程是否完成。如果异步方法已经完成,原始线程就调用EndInvoke并继续。否则,它做一些其它处理,然后过一会儿再检查。如下图:

这段代码产生了如下输出。

回调模式

  在之前的等待模式与轮询模式中,初始线程继续它自己的控制流程,直到它知道开启的线程完成。然后,它获取结果并继续。

  回调模式的不同之处在于,一旦初始线程发起了异步方法,它就自己管自己了,不再考虑同步。当异步方法调用结束之后,系统调用一个用户自定义的方法来处理结束,并且调用委托的EndInvoke方法。这个用户自定义的方法叫做回调方法或回调。

  BeginInvoke的参数列表中最后的两个额外参数被回调方法用做:

    1)  第一个参数,callback参数,是回调方法的名字。

    2)  第二个参数,state参数,可以是null或要传入回调方法的一个对象数据。我们可以通过使用IAsyncResult参数的AsyncState属性来获取这个对象。参数类型是object

  1. 回调方法的签名和返回类型必须和AsyncCallback委托类型所描述的形式一致。它需要方法接受一个IAsyncResult作为参数并且返回类型是void。如下所示:

Void AsyncCallback(IAsyncResult iar)

  1. 在回调方法内,我们的代码应该调用委托的EndInvoke方法来处理异步方法执行后的输出值。要调用委托的EndInvoke方法,我们肯定需要委托对象的引用,而它在初始线程中,不在开启线程中。如果我们不使用BeginInvoke的state参数作其它的用途,可以使用它发送委托的引用给回调方法。否则,我们可以从发送给方法作为参数的IAsyncResult对象中提取出委托的引用。

    1)  给回调方法的参数只有一个,就是刚结束的异步方法的IAsyncResult接口的引用,要记住,IAsyncResult接口对象在AsyncResult类对象的内部。

    2)  尽管IAsyncResult接口没有委托对象的引用,而包含它的AsyncResult类对象却有委托对象的引用。

    3)  有了类对象的引用,我们现在就可以调用类对象的AsyncDelegate属性并且把它转化为合适的委托类型。这样就得到了委托引用,我们可以用它来调用EndInvoke。

如下代码所示:

这段代码产生了如下输出。

那么以上的异步内容已经基本讲解完毕。

说明:异步编程在.Net4.0中,有了更好的方式处理,简化了编程的复杂度,使用Task类(在System.Threading.Tasks命名空间中)处理,但原理是一样的。

C#如何使用异步编程的更多相关文章

  1. C#异步编程(一)

    异步编程简介 前言 本人学习.Net两年有余,是第一次写博客,虽然写的很认真,当毕竟是第一次,肯定会有很多不足之处, 希望大家照顾照顾新人,有错误之处可以指出来,我会虚心接受的. 何谓异步 与同步相对 ...

  2. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

  3. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  4. 异步编程 In .NET

    概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们 ...

  5. C#异步编程(二)

    async和await结构 序 前篇博客异步编程系列(一) 已经介绍了何谓异步编程,这篇主要介绍怎么实现异步编程,主要通过C#5.0引入的async/await来实现. BeginInvoke和End ...

  6. [.NET] 利用 async & await 的异步编程

    利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html  目录 异步编程的简介 异 ...

  7. [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程

    怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html  ...

  8. [C#] 走进异步编程的世界 - 开始接触 async/await

    走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async/await,但在控制台输出示例时经常会采用 C# 6.0 的 $&qu ...

  9. C#异步编程

    什么是异步编程 什么是异步编程呢?举个简单的例子: using System.Net.Http; using System.Threading.Tasks; using static System.C ...

  10. 深入解析js异步编程利器Generator

    我们在编写Nodejs程序时,经常会用到回调函数,在一个操作执行完成之后对返回的数据进行处理,我简单的理解它为异步编程. 如果操作很多,那么回调的嵌套就会必不可少,那么如果操作非常多,那么回调的嵌套就 ...

随机推荐

  1. ssh框架搭建错误集合

    1,把jsp放入到WEB-INF/view目录下,struts2.xml配置<result name="success">/WEB-INF/view/home.jsp& ...

  2. Spring3系列4-多个配置文件的整合

    Spring3系列4-多个配置文件的整合 在大型的Spring3项目中,所有的Bean配置在一个配置文件中不易管理,也不利于团队开发,通常在开发过程中,我们会按照功能模块的不同,或者开发人员的不同,将 ...

  3. win2008远程桌面会话数增加

    1.[解决]由于没有远程桌面授权服务器可以提供许可证,远程回话被中断 你看到的这个文章来自于http://www.cnblogs.com/ayanmw 由于windows server 2008 R2 ...

  4. Win7下安装配置gVim

    本文根据vim官网的<Simple Steps to Help You Install gVim on Windows 7>[1]一文整理而成. 1. 下载gVim 在http://www ...

  5. mac安装 配置 ant

    转自:http://blog.sina.com.cn/s/blog_877e9c3c0101qs87.html 1.下载ant 官网下载 http://ant.apache.org/bindownlo ...

  6. 跟随标准与Webkit源码探究DOM -- 获取元素之getElementById

    按照ID获取元素 -- getElementById 标准 DOM 1,定义在HTMLDocument Interface 中,原型Element getElementById(in DOMStrin ...

  7. mysql日期类型默认值'0000-00-00'容错处理

    mysql日期默认值'0000-00-00'惹的祸 .net连mysql数据库时,如果表里有字段是日期型且值是‘0000-00-00’时,会报错.在C#里面日期不可能是那样的.或许是最小日期定义的差别 ...

  8. nginx后的tomcat获取真实用户ip

    目前大部分获取ip的方式:beat.getRequest().getRemoteAddr()但是,如果通过nginx反向代理的话,就获取不到真实ip,是获取的nginx的ip 需要:添加    pro ...

  9. SQL server 数据库连接方式分析

    SQL server 数据库连接方式图示: ODBC和OLEDB连接的区别 ODBC(开放数据库互连):是Microsoft引进的一种早期数据库接口技术.它实际上是ADO的前身.早期的数据库连接是非常 ...

  10. Caching查看窗口

    闲来无事,做了一个简约的Caching查看窗口,可以方便的查看本地缓存的使用情况: 下面的URL和VersionNum用来查看某个特定资源的特定版本是否存在,分别输入所需信息,点击“检测”,即可在下面 ...