Microsoft.NET Framework环境中异步编程浅析
2010-08-30曲卫华
曲卫华
(太原大学 计算中心,山西 太原 030009)
Microsoft.NET Framework环境中异步编程浅析
曲卫华
(太原大学 计算中心,山西 太原 030009)
Microsoft.NET Framework环境中异步编程是非常重要的,学好异步编程可以提高初学者和科研人员的程序技巧和思维能力,有必要介绍分析异步编程模式和原理,帮助学习者在Microsoft.NET Framework下提高编程能力。
异步编程;设计模式;异步调用
文章编号:1671-5977(2010)02-0116-04
Visual Studio是一套完善的工具,用于生成桌面程序和基于团队的企业级Web应用程序。除了生成高性能的桌面应用程序外,还可以使用Visual Studio的基于组件的强大开发工具和其他技术,简化企业级解决方案的基于团队的设计、开发和部署。
异步操作通常用于执行完成时间可能较长的任务,如打开大文件、连接远程计算机或查询数据库。异步操作在主应用程序线程以外的线程中执行。应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行。
.NET Framework为异步操作提供两种设计模式:
(1)使用IAsyncResult对象的异步操作。
(2)使用事件的异步操作。
(3)IAsyncResult设计模式允许多种编程模型,但更加复杂不易学习,可提供大多数应用程序都不要求的灵活性。可能的话,类库设计者应使用事件驱动模型实现异步方法。在某些情况下,库设计者还应实现基于IAsyncResult的模型。
1 异步编程模式概述
使用IAsyncResult设计模式的异步操作是通过名为Begin操作名称和End操作名称的两个方法来实现的,这两个方法分别开始和结束异步操作操作名称。例如,FileStream类提供BeginRead和EndRead方法来从文件异步读取字节。这两个方法实现了Read方法的异步版本。
在调用Begin操作名称后,应用程序可以继续在调用线程上执行指令,同时异步操作在另一个线程上执行。每次调用Begin操作名称时,应用程序还应调用End操作名称来获取操作的结果。
1.1 begin操作方法
Begin操作名称方法开始异步操作操作名称并返回一个实现 IAsyncResult接口的对象。IAsyncResult对象存储有关异步操作的信息。下表提供了有关异步操作的信息。
表1 begin操作方法
Begin操作名称方法带有该方法的同步版本的签名中声明的任何参数(由值传递或由引用传递)。Begin操作名称方法签名中不包含任何输出参数。Begin操作名称方法签名另外还包括两个参数。在这两个参数中,第一个参数定义一个AsyncCallback委托,此委托引用在异步操作完成时调用的方法。如果调用方不希望在操作完成后调用方法,它可以指定null(在Visual Basic中为Nothing)。第二个参数是一个用户定义的对象。此对象可用来向异步操作完成时调用的方法传递应用程序特定的状态信息。如果Begin操作名称方法还带有其他一些操作特定的参数(例如,一个用于存储从文件读取的字节的字节数组),则AsyncCallback和应用程序状态对象将是Begin操作名称方法签名中的最后两个参数。
开始操作名称立即返回对调用线程的控制。如果Begin操作名称方法引发异常,则会在开始异步操作之前引发异常。如果Begin操作名称方法引发异常,则意味着没有调用回调方法。
End操作名称方法可结束异步操作操作名称。End操作名称方法的返回值与其同步副本的返回值类型相同,并且是特定于异步操作的。例如,EndRead方法返回从 FileStream读取的字节数,EndGetHostByName方法返回包含有关主机的信息的IPHostEntry对象。End操作名称方法带有该方法同步版本的签名中声明的所有输出参数或引用参数。除了来自同步方法的参数外, End操作名称方法还包括IAsyncResult参数。调用方必须将对应调用返回的实例传递给Begin操作名称。
如果调用 End操作名称时 IAsyncResult对象表示的异步操作尚未完成,则End操作名称将在异步操作完成之前阻止调用线程。异步操作引发的异常是从End操作名称方法引发的。未定义多次使用同一 IAsyncResult调用 End操作名称方法的效果。同样,也未定义使用非相关的Begin方法返回的 IAsyncResult调用 End操作名称方法的效果。
1.2
对于访问异步操作的结果,应用程序开发人员有若干种设计选择。正确的选择取决于应用程序是否有可以在操作完成时执行的指令。如果应用程序在接收到异步操作结果之前不能进行任何其他工作,则必须先阻止该应用程序进行其他工作,等到获得这些操作结果后再继续进行。若要在异步操作完成之前阻止应用程序,您可以使用下列方法之一:
(1)从应用程序的主线程调用 EndOperationName,阻止应用程序执行,直到操作完成之后再继续执行。有关演示此方法的示例,请参见通过结束异步操作来阻止应用程序执行。
(2)使用AsyncWaitHandle来阻止应用程序执行,直到一个或多个操作完成之后再继续执行。有关演示此方法的示例,请参见使用AsyncWaitHandle阻止应用程序的执行。
在异步操作完成时不需要阻止的应用程序可使用下列方法之一:
(1)按以下方式轮询操作完成状态:定期检查IsCompleted属性,操作完成后调用EndOperationName。有关演示此方法的示例,请参见轮询异步操作的状态。
(2)使用AsyncCallback委托来指定操作完成时要调用的方法。有关演示此方法的示例,请参见使用AsyncCallback委托结束异步操作。
2 、使用异步调用同步方法
.NET Framework允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义BeginInvoke和EndInvoke方法。
BeginInvoke方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个AsyncCallback委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke立即返回,不等待异步调用完成。BeginInvoke会返回IAsyncResult,这个结果可用于监视异步调用进度。
EndInvoke方法检索异步调用的结果。调用BeginInvoke后可随时调用 EndInvoke方法;如果异步调用尚未完成,EndInvoke将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke的参数包括您需要异步执行的方法的out和ref参数(在Visual Basic中为
图1 调用同步方法代码
2.1 调用BeginInvoke之后,您可以执行下列操作:
(1)进行某些操作,然后调用EndInvoke一直阻止到调用完成。
(2)使用 System.IAsyncResult.AsyncWait-Handle属性获取WaitHandle,使用它的WaitOne方法一直阻止执行直到发出WaitHandle信号,然后调用EndInvoke。
(3)轮询由BeginInvoke返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。
(4)将用于回调方法的委托传递给BeginInvoke。异步调用完成后,将在 ThreadPool线程上执行该方法。该回调方法将调用 EndInvoke。
2.2 定义测试方法和异步委托
下面的代码示例演示异步调用同一个长时间运行的方法 TestMethod的各种方式。Test-Method方法会显示一条控制台消息,说明它已开始处理,休眠了几秒钟,然后结束。TestMethod有一个out参数,该参数用于演示此种参数添加到BeginInvoke和 EndInvoke的签名中的方式。您可以按同样的方式处理ref参数。
下面的代码示例演示 TestMethod的定义和名为 AsyncMethodCaller的、可用来异步调用TestMethod的委托。若要编译任何代码示例,必须包括 TestMethod的定义和AsyncMethodCaller委托。
2.3 使用EndInvoke等待异步调用
异步执行方法最简单的方式是通过调用委托的BeginInvoke方法来开始执行方法,在主线程上执行一些工作,然后调用委托的 EndInvoke方法。EndInvoke可能会阻止调用线程,因为它直到异步调用完成之后才返回。这种技术非常适合文件或网络操作,但是由于EndInvoke会阻止它,所以不要从服务于用户界面的线程中调用它。
2.4 使用WaitHandle等待异步调用
您可以使用BeginInvoke返回的 IAsyncResult的 AsyncWaitHandle属性来获取 Wait-Handle。异步调用完成时会发出WaitHandle信号,而您可以通过调用WaitOne方法等待它。如果您使用WaitHandle,则在异步调用完成之前或之后,在通过调用EndInvoke检索结果之前,还可以执行其他处理。
2.5 轮询异步调用完成
可以使用由BeginInvoke返回的 IAsyncResult的 IsCompleted属性来发现异步调用何时完成。从用户界面的服务线程中进行异步调用时可以执行此操作。轮询完成允许调用线程在异步调用在ThreadPool线程上执行时继续执行。
图2 轮询异步调用
2.6 异步调用完成时执行回调方法
如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法。回调方法在ThreadPool线程上执行。
若要使用回调方法,必须将引用回调方法的AsyncCallback委托传递给BeginInvoke。也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便回调方法能够调用EndInvoke。
3 基于事件的异步模式概述
那些同时执行多项任务、但仍能响应用户交互的应用程序通常需要实施一种使用多线程的设计方案。System.Threading命名空间提供了创建高性能多线程应用程序所必需的所有工具,但要想有效地使用这些工具,需要有丰富的使用多线程软件工程的经验。对于相对简单的多线程应用程序,BackgroundWorker组件提供了一个简单的解决方案。对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类。
3.1 基于事件的异步模式的特征
基于事件的异步模式可以采用多种形式,具体取决于某个特定类支持的操作的复杂程度。最简单的类可能只有一个MethodNameAsync方法和一个对应的 MethodNameCompleted事件。更复杂的类可能有若干个MethodNameAsync方法(每种方法都有一个对应的MethodNameCompleted事件),以及这些方法的同步版本。这些类分别支持各种异步方法的取消、进度报告和增量结果。
异步方法可能还支持多个挂起的调用(多个并行调用),允许您的代码在此方法完成其他挂起的操作之前调用此方法任意多次。若要正确处理此种情况,必须让您的应用程序能够跟踪各个操作的完成。
3.2 基于事件的异步模式示例
SoundPlayer和 PictureBox组件表示基于事件的异步模式的简单实现。WebClient和BackgroundWorker组件表示基于事件的异步模式的更复杂的实现。
这里虚构的AsyncExample类有两个方法,都支持同步和异步调用。同步重载的行为类似于方法调用,它们对调用线程执行操作;如果操作很耗时,则调用的返回可能会有明显的延迟。异步重载将在另一个线程上启动操作,然后立即返回,允许在调用线程继续执行的同时让操作“在后台”执行。
3.3 异步方法重载
异步操作可以有两个重载:单调用和多调用。您可以通过方法签名来区分这两种形式:多调用形式有一个额外的参数,即userState。使用这种形式,您的代码可以多次调用 Method1 Async(string param,object userState),而不必等待任何挂起的异步操作的完成。另一方面,如果您尝试在前一个调用尚未完成时调用Method1 Async(string param),该方法将引发InvalidOperationException。
4 小结
异步编程是.NET Framework环境中高级开发的一种技术,系统了解异步编程对科研人员更好的掌握.NET Framework其内涵和原理有重要的理论价值和现实意义。
[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.
[4]Matthew MacDonald,Mario Szpuszta,博思工作室. ASP.NET高级程序设计(第3版)[M].北京:人民邮电出版社,2009.
[5]张跃廷.ASP.NET开发实战宝典[M].北京:清华大学出版社,2010.
[责任编辑:赵自谦]
The Analysis of Asynchronous Programming in Microsoft.NET Framework Environment
QU Wei-hua
(Computer Center,Taiyuan University,Taiyuan,030009,China)
Asynchronous programming is very important is Microsoft.NET Framework environment.It can help the beginners and researchesr to better their programming skills and improve their thinking abilities to learn aoynchronous programming well.It is necessary to introduce and analyze the asynchronousprogramming model and principle,help learners enhance ability of programming in Microsoft.net Framework.
asynchronous programming;programming model;asychronous call
book=2010,ebook=69
TP314
A
2010-04-19
曲卫华(1982-),男,山西静乐人,工学硕士,太原大学计算中心助教。