C#如何使用异步编程

怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法。委托类有两个方法,叫做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。如下所示:

  1. Void AsyncCallback(IAsyncResult iar) 
  1. 在回调方法内,我们的代码应该调用委托的EndInvoke方法来处理异步方法执行后的输出值。要调用委托的EndInvoke方法,我们肯定需

    要委托对象的引用,而它在初始线程中,不在开启线程中。如果我们不使用BeginInvoke的state参数作其它的用途,可以使用它发送委托的引用给
    回调方法。否则,我们可以从发送给方法作为参数的IAsyncResult对象中提取出委托的引用。

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

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

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

如下代码所示:

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

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

作者:殇曲?

来源:51CTO

时间: 2024-10-06 05:14:28

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

对 ASP.NET 异步编程的一点理解

本来这篇博文想探讨下异步中的异常操作,但自己在做异步测试的时候,又对 ASP.NET 异步有了新的认识,可以说自己之前对异步的理解还是有些问题,先列一下这篇博文的三个解惑点: async await 到底是什么鬼??? 异步操作中发生异常,该如何处理? 异步操作中发生异常(有无 catch throw 情况),Application_Error 会不会捕获? 之前测试过异步中的同步(很多种情况),这次我们把测试代码写更复杂些(异步中再进行异步),代码如下: [Route("")]  [

Javascript异步编程的4种方法

你可能知道,Javascript语言的执行环境是"单线程"(single thread). 所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推. 这种模式的好处是实现起来比较简单,执行环境相对单纯:坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.常见的浏 览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其

C#编程总结(六)异步编程

1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程 计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个 操作时,应用程序可在异步方法执行其任务时继续执行. 2.同步与异步的区别 同步 (Synchronous):在执行某个操作时,应用程序必须等待该操作执行完成后才能继续执行. 异 步(Asynchronous):在执行某个操作时,应用程序可在异步操作执行时继续执行.实质:异步操作, 启动了新的线程,主线程与方法线程并行执行

如何设计一门编程语言(八) 异步编程和CPS变换

关于这个话题,其实在(六)里面已经讨论了一半了.学过Haskell的都知道,这个世界上很多东西都可以用monad和comonad来把一些复杂的代码给抽象成简单的.一看就懂的形式.他们的区别,就像用js做一个复杂的带着几层循环的动画,直接写出来和用jquery的"回调"写出来的代码一样.前者能看不能用,后者能用不能看.那有没有什么又能用又能看的呢?我目前只能在Haskell.C#和F#里面看到.至于说为什么,当然是因为他们都支持了monad和comonad.只不过C#作为一门不把&quo

Generator与异步编程概述

在<深入浅出Node.js>的第4章里,笔者深入地介绍了当前盛行在Node和前端JavaScript中的几种异步编程的解决方案,唯独对Generator的解决方案没有介绍.但随着Node版本的升级和ECMAScript harmony的特性不断得到支持,在0.11版本中,我们可以通过启用--harmory参数让V8支持Generator.最近Connect/Express背后的开发团队也将精力转移到新的库和框架上,这个核心库和框架就是co和koa,它们最主要的特点主要就是基于ECMAScrip

Asp.Net异步编程知识

写在前面的话,很久没有写Blog了,不对,其实一致就没有怎么写过.今天有空,我也来写一篇Blog 随着.Net4.5的推出,一种新的编程方式简化了异步编程,在网上时不时的也看到各种打着Asp.Net异步编程的口号,如何提高性能,如何提高吞吐率! 好多文章都说得不清楚,甚至是错误的.只看到了一些表现,混淆概念.希望这篇文章能够能够对一部分人理解Asp.net异步编程模型. 1基础知识,谈一个初学者不容易理解的基础知识,这个基础知识,很不基础的哦 先看这个代码 ThreadPool.GetMaxTh

Windows 8 Store Apps学习(45) 多线程之异步编程: IAsyncAction

多线程之异步编程: IAsyncAction, IAsyncOperation 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress 介绍 重新想象 Windows 8 Store Apps 之 异步编程 IAsyncAction - 无返回值,无进度值 IAsyncOperation - 有返回

Windows 8 Store Apps学习(44) 多线程之异步编程

多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 介绍 重新想象 Windows 8 Store Apps 之 异步编程 经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例 1.使用经典的异步编程模型(IAsyncResult)实现一个支持异步操作的类 Thread/Async/ClassicAsync.cs /*

C#基础学习 —— 异步编程篇 (二)

基于事件的异步模式是比 IAsyncResult 模式更高级的一种异步编程模式,也被用在更多的场合.对于相对简单的应用程序可以直接用 .Net 2.0 新增的 BackgroundWorker 组件来很方便的实现,对于更复杂的异步应用程序则需要自己实现一个符合基于事件的异步模式的类.这两者对我都是新东西,先从简单的入手,下一篇里我再去尝试复杂类模型的实现 模式概述 支持基于事件的异步模式的类会有若干个 MethodNameAsync 方法表示开始异步操作,并有对应的 MethodNameComp

用 Groovy+Jetty 快速实现 Web 异步编程

为什么要异步编程 在现在大规模高并发的 WEB 应用中,由于硬件及网络的限制,I/O 处理速度相当较慢,往往 成为 WEB 系统的性能瓶颈.Node.js 通过非阻塞的 IO 和事件驱动很好的缓解了 Web 服务器在高并发时的资源占用,极大 的提高了 WEB 服务器对高并发的处理能力.同时 Node.js 带来的轻量快捷的异步编程给 WEB 开发带来了一股清新的空气 .那么对于广大的 Java 开发者来说,是否可以实现类似的 WEB 开发呢,答案是肯定的.利用 Groovy 动态语言.Jetty