2024年3月8日发(作者:)

2010年6月 太原大学学报 第11卷第2期总第42期 Journal of Taiyuan University Vo1.1lNo.2 SumNo.42 文章编号:1671—5977(2010)02—0116—04 Microsoft.NET Framework环境中异步编程浅析 曲卫华 (太原大学计算中心,山西太原030009) 摘要:Microsoft.NETFramework环境中异步编程是非常重要的,学好异步编程可以提高初学者和科研 人员的程序技巧和思维能力,有必要介绍分析异步编程模式和原理,帮助学习者在Microsoft.NETFramework 下提高编程能力。 关键词:异步编程;设计模式;异步调用 中图分类号:TP314 文献标识码:A Visual Studio是一套完善的工具,用于生成 个方法实现了Read方法的异步版本。 桌面程序和基于团队的企业级web应用程序。 在调用Begin操作名称后,应用程序可以继 除了生成高性能的桌面应用程序外,还可以使用 续在调用线程上执行指令,同时异步操作在另一 Visual Studio的基于组件的强大开发工具和其他 个线程上执行。每次调用Begin操作名称时,应 技术,简化企业级解决方案的基于团队的设计、 用程序还应调用End操作名称来获取操作的结 开发和部署。 果。 异步操作通常用于执行完成时间可能较长 1.1 begin操作方法 的任务,如打开大文件、连接远程计算机或查询 Begin操作名称方法开始异步操作操作名称 数据库。异步操作在主应用程序线程以外的线 并返回一个实现IAsyncResult接H的对象。I— 程中执行。应用程序调用方法异步执行某个操 AsyncResult对象存储有关异步操作的信息。下 作时,应用程序可在异步方法执行其任务时继续 表提供了有关异步操作的信息。 执行。 表1 begin操作方法 .NET Framework为异步操作提供两种设计 成员 说明 模式: A一syncState 包含有关异步操作的信息个可选的应用程序特定的对象, 。 (1)使用IA ̄syncResult对象的异步操作。 一(2)使用事件的异步操作。 AsyncWaitHandle 作完成之前阻止应用程序执行个WaitHandle,可用来在异步操 。 (3)IAsyncResult设计模式允许多种编程模 一个值,指示异步操作是否是在用 型,但更加复杂不易学习,可提供大多数应用程 Completed 于调用Begin操作名称的线程上完 序都不要求的灵活性。可能的话,类库设计者应 Synchronously 成,而不是在单独的ThreadPool线 程上完成。 使用事件驱动模型实现异步方法。在某些情况 IsCompleted 一个值,指示异步操作是否已完成。 下,库设计者还应实现基于IAsyncResult的模型。 Begin操作名称方法带有该方法的同步版本 1异步编程模式概述 的签名中声明的任何参数(由值传递或由引用传 使用IAsyneResult设计模式的异步操作是通 递)。Begin操作名称方法签名中不包含任何输 过名为Begin操作名称和End操作名称的两个方 出参数。Begin操作名称方法签名另外还包括两 法来实现的,这两个方法分别开始和结束异步操 个参数。在这两个参数中,第一个参数定义一个 作操作名称。例如,FileStream类提供BeginRead AsyncCallback委托,此委托引用在异步操作完成 和EndRead方法来从文件异步读取字节。这两 时调用的方法。如果调用方不希望在操作完成 收稿日期:2010—04—19 作者简介:曲卫华(1982一),男,山西静乐人,工学硕士,太原大学计算中心助教。 ・ 116・ 

后调用方法,它可以指定null(在Visual Basic中 (2)使用AsyncWaitHandle来阻止应用程序 为Nothing)。第二个参数是一个用户定义的对 执行,直到一个或多个操作完成之后再继续执 象。此对象可用来向异步操作完成时调用的方 行。有关演示此方法的示例,请参见使用 tHandle阻止应用程序的执行。 法传递应用程序特定的状态信息。如果Begin操 AsyncWai在异步操作完成时不需要阻止的应用程序 作名称方法还带有其他一些操作特定的参数(例  如,一个用于存储从文件读取的字节的字节数 可使用下列方法之一:(1)按以下方式轮询操作完成状态:定期检 组),则AsyncCallback和应用程序状态对象将是 Begin操作名称方法签名中的最后两个参数。 查IsCompleted属性,操作完成后调用EndOpera— onName。有关演示此方法的示例,请参见轮询 开始操作名称立即返回对调用线程的控制。 ti 如果Begin操作名称方法引发异常,则会在开始 异步操作的状态。异步操作之前引发异常。如果Begin操作名称方 法引发异常,则意味着没有调用回调方法。 (2)使用AsyncCallback委托来指定操作完成 时要调用的方法。有关演示此方法的示例,请参 lback委托结束异步操作。 End操作名称方法可结束异步操作操作名 见使用AsyncCal2、使用异步调用同步方法 称。End操作名称方法的返回值与其同步副本的 返回值类型相同,并且是特定于异步操作的。例 .NET Framework允许您异步调用任何方 如,EndRead方法返回从FileStream读取的字节 法。为此,应定义与您要调用的方法具有相同签 数,EndGetHostByName方法返回包含有关主机 名的委托;公共语言运行库会自动使用适当的签 nlnvoke和EndInvoke方法。 的信息的IPHostEntry对象。End操作名称方法 名为该委托定义BegiBeginInvoke方法可启动异步调用。它与您 带有该方法同步版本的签名中声明的所有输出 需要异步执行的方法具有相同的参数,另外它还 yncCall— End操作名称方法还包括IAsyncResult参数。调 有两个可选参数。第一个参数是一个As用方必须将对应调用返回的实例传递给Begin操 back委托,该委托引用在异步调用完成时要调用 的方法。第二个参数是一个用户定义的对象,该 作名称。 nInvoke立即 如果调用End操作名称时IAsyncResult对 对象可向回调方法传递信息。Begi参数或引用参数。除了来自同步方法的参数外, nInvoke会返回 象表示的异步操作尚未完成,则End操作名称将 返回,不等待异步调用完成。BegiAsyncResult,这个结果可用于监视异步调用进 在异步操作完成之前阻止调用线程。异步操作 I引发的异常是从End操作名称方法引发的。未 定义多次使用同一IAsyncResult调用End操作 度。 EndInvoke方法检索异步调用的结果。调用 nlnvoke后可随时调用Endlnvoke方法;如果 名称方法的效果。同样,也未定义使用非相关的 Begi异步调用尚未完成,EndInvoke将一直阻止调用 Begin方法返回的IAsyncResult调用End操作名 线程,直到异步调用完成后才允许调用线程执 称方法的效果。 1.2 行。EndInvoke的参数包括您需要异步执行的方 对于访问异步操作的结果,应用程序开发人 员有若干种设计选择。正确的选择取决于应用 程序是否有可以在操作完成时执行的指令。如 果应用程序在接收到异步操作结果之前不能进 法的out和ref参数(在Visual Basic中为<Out> ByRef和ByRef)以及由Beginlnvoke返回的I— AsyncResult。 u s ing絮 tBe-m 。“ w q一 ”  “ 。 一 “” 一。 一 “一行任何其他工作,则必须先阻止该应用程序进行 其他工作,等到获得这些操作结果后再继续进 ;-_=b t。 。。 嚣 } t札 nl‘.1l性 蠹 th。d b.时一 ) 行。若要在异步操作完成之前阻止应用程序,您 可以使用下列方法之一: , t Th u  d S 椎 蜱‘"“string.F口r ( e del∞ te…tt v11 e li h…" ch…the… jv 1q t…。 ~ ∞u t… . tn) r c.1lDmt—T t ll孽() 。 h "th (1)从应用程序的主线程调用EndOpera— tionName,阻止应用程序执行,直到操作完成之后 再继续执行。有关演示此方法的示例,请参见通 一 P曲l 。de1 g山) str ̄9^‘,nd‘・th。dc・ll砸・(in‘e^llD……t nt t ●・dId) 图1调用同步方法代码 2.i 调用BeginInvoke之后,您可以执行下 过结束异步操作来阻止应用程序执行。 列操作: ・ 117・ 

(1)进行某些操作,然后调用Endlnvoke一直 suit的IsCompleted属性来发现异步调用何时完 阻止到调用完成。 成。从用户界面的服务线程中进行异步调用时 (2)使用System.IAsyncResult.AsyncWait— 可以执行此操作。轮询完成允许调用线程在异 Handle属性获取WaitHandle,使用它的WaitOne 步调用在ThreadPool线程上执行时继续执行。 方法一直阻止执行直到发出WaitHandle信号,然 后调用Endlnvoke。 ul Dg自 l岫 h・耐1 …b_椰 ’ …^"“ 。鼬‘O ’n… 二: :: } (3)轮询由Beginlnvoke返回的IAsyncRe— sult,确定异步调用何时完成,然后调用Endln— : : 一… … “ 盘 溢: 嚣 … i .一 t.d 州, vokeo (4)将用于回调方法的委托传递给BeginIn— voke。异步调用完成后,将在ThreadPool线程上 执行该方法。该回调方法将调用Endlnvoke。 2.2定义测试方法和异步委托 下面的代码示例演示异步调用同一个长时 间运行的方法TestMethod的各种方式。Test— Method方法会显示一条控制台消息,说明它已开 始处理,休眠了几秒钟,然后结束。TestMethod 有一个out参数,该参数用于演示此种参数添加 到Beginlnvoke和EndInvoke的签名中的方式。 您可以按同样的方式处理reI参数。 下面的代码示例演示TestMethod的定义和 名为AsyneMethodCaller的、可用来异步调用 TestMethod的委托。若要编译任何代码示例,必 须包括TestMethod的定义和AsyncMethodCaller 委托。 2.3使用Endlnvoke等待异步调用 异步执行方法最简单的方式是通过调用委 托的Beginlnvoke方法来开始执行方法,在主线 程上执行一些工作,然后调用委托的Endlnvoke 方法。Endlnvoke可能会阻止调用线程,因为它 直到异步调用完成之后才返回。这种技术非常 适合文件或网络操作,但是由于Endlnvoke会阻 止它,所以不要从服务于用户界面的线程中调用 它。 2.4使用WaitHandle等待异步调用 您可以使用BeginInvoke返回的IAsyncRe— sult的AsyncWaitHandle属性来获取Wait— Handle。异步调用完成时会发出WaitHandle信 号,而您可以通过调用WaitOne方法等待它。如 果您使用WaitHandle,则在异步调用完成之前或 之后,在通过调用EndInvoke检索结果之前,还可 以执行其他处理。 2.5轮询异步调用完成 可以使用由Beginlnvoke返回的IAsyncRe一 ・118・ :. 兰: : 0¨tNId 1. 罐兰;誉耋蒜 = -- t : 篙 毒 := :: 嚣 = : , 。 盘;t. :: : = 。 ”’ … “”‘。 ) , 图2轮询异步调用 2.6异步调用完成时执行回调方法 如果启动异步调用的线程不需要是处理结 果的线程,则可以在调用完成时执行回调方法。 回调方法在ThreadPool线程上执行。 若要使用回调方法,必须将引用回调方法的 AsyncCallback委托传递给BeginInvoke。也可以 传递包含回调方法将要使用的信息的对象。例 如,可以传递启动调用时曾使用的委托,以便回 调方法能够调用EndInvoke。 3基于事件的异步模式概述 那些同时执行多项任务、但仍能响应用户交 互的应用程序通常需要实施一种使用多线程的 设计方案。System.Threading命名空间提供了创 建高性能多线程应用程序所必需的所有工具,但 要想有效地使用这些工具,需要有丰富的使用多 线程软件工程的经验。对于相对简单的多线程 应用程序,BackgroundWorker组件提供了一个简 单的解决方案。对于更复杂的异步应用程序,请 考虑实现一个符合基于事件的异步模式的类。 3.1基于事件的异步模式的特征 基于事件的异步模式可以采用多种形式,具 体取决于某个特定类支持的操作的复杂程度。 最简单的类可能只有一个MethodNameAsync方 法和一个对应的MethodNameCompleted事件。 更复杂的类可能有若干个MethodNameAsync方 法(每种方法都有一个对应的MethodNameCom— pleted事件),以及这些方法的同步版本。这些类 分别支持各种异步方法的取消、进度报告和增量 结果。 异步方法可能还支持多个挂起的调用(多个 并行调用),允许您的代码在此方法完成其他挂 

起的操作之前调用此方法任意多次。若要正确 您尝试在前一个调用尚未完成时调用Methodl 处理此种情况,必须让您的应用程序能够跟踪各 Async(string param),该方法将引发InvalidOper— 个操作的完成。 ationException。 3.2基于事件的异步模式示例 4小结 SoundPlayer和PictureBox组件表示基于事 异步编程是.NET Framework环境中高级开 件的异步模式的简单实现。WebClient和Back 发的一种技术,系统了解异步编程对科研人员更 groundWorker组件表示基于事件的异步模式的 好的掌握.NET Framework其内涵和原理有重要 更复杂的实现。 的理论价值和现实意义。 这里虚构的AsyncExample类有两个方法, 参考文献: 都支持同步和异步调用。同步重载的行为类似 [1]Yack D.,Mayo J..ASP.NET 2.0编程珠玑:来自 于方法调用,它们对调用线程执行操作;如果操 MVP的权威开发指南[M].北京:清华大学出版社,2006. 作很耗时,则调用的返回可能会有明显的延迟。 [2]Andrew troelsen,朱晔,肖逵,等.C#与NET 3.5高级 异步重载将在另一个线程上启动操作,然后立即 程序设计(第4版)[M].北京:人民邮电出版社,2009. 返回,允许在调用线程继续执行的同时让操作 [3]Matthew macdonald,王德才.WPF编程宝典:使用C# “在后台”执行。 2008和NET 3.5(第2版)[M].北京:清华大学出版社, 2009. 3.3异步方法重载 [4]Matthew MacDonald,Mario Szpuszta,博思工作室. 异步操作可以有两个重载:单调用和多调 ASP.NET高级程序设计(第3版)[M].北京:人民邮电 用。您可以通过方法签名来区分这两种形式:多 出版社,2009. 调用形式有一个额外的参数,即userState。使用 [5]张跃廷.ASP.NET开发实战宝典[M].北京:清华大 这种形式,您的代码可以多次调用Methodl 学出版社,2010. Async(string param,object userState),而不必等 待任何挂起的异步操作的完成。另一方面,如果 [责任编辑:赵自谦] The Analysis of Asynchronous Programming in Microsoft.NET Framework Environment QuWei-hua (Computer Center,Taiyuan University,Taiyuan,030009,China) Abstract:Asynchronous programming is very important is Microsoft.NET Framework environment.It can help the begin— nets and researchesr tO better their programming skills and improve their thinking abilities tO learn aoynchronous programming wel1.It is necessary to introduce and analyze the asynchronous programming model and principle,help learners enhance ability of programmign in Microsoft.net Framework. Key words:asynchronous programming;programming model;asyehmnous call (上接第104页) Knowledge and Practice on Practice Talent LIU Juan ,CAI Zhou-ming2 (1.Architecture Engineering Department,Taiyuan University,Taiyuan,030009,China; 2.Guangdong Jieyang City Zhendong Construction nad Installation Corporation,Jieyang,515041,China) Abstract:The personnel needed in the construction market has the characteristic of aimign directly at post and having higher practical capactity.So cultivatign studenm’practiacl capacity and raisign their level of post skills Can reach the purpose for stu— dents to come into contact with their[costs in“zero distance’’of“short distance”. Key words:practica1 capability;post skills;cultivation of talents ・ 119・