第10章 异步编程模式
【摘要】:异步编程充分利用多线程技术带来的好处,而不需要程序员了解多线程开发中的复杂细节。本章讲述了基于IAsyncResult的异步模式、基于事件的异步模式。
第1节 程序的同步执行和异步执行
1、同步概念:
若在代码中调用了一个方法,需要等待此方法所有的代码执行完毕之后,才能回到原来的地方执行下一行代码,这种程序运行方式称为同步。
2、异步概念:
在调用方法之后,不用等待方法执行完成就马上执行下一条语句,这种程序运行方式称为异步。
3、异步调用的本质:不在主线程中执行,而在另一辅助线程中与主线程并行执行。
第2节 基于委托的异步编程模式
1、 当定义一个委托时,编译器会生成如下的类,借助委托的BeginInvoke和EndInvoke方法实现异步调用。
Public sealed class CalculateFolderSizeDelegate:MulticastDelegate
{
Public CalculateFolderSizeDelegate(object target,int methodPtr)
{ ……}
Public virtual <方法返回值类型> Invoke (<输入和输出参数>)
{ ……}
Public virtual IAsyncResult BeginInvoke(<输入和输出变量>,AsyncCallback callback,object asyncState)
{ ……}
Public virtual <方法返回值类型> EndInvoke(<声明为ref或out的参数>,IAsyncResult result)
{ ……}
A、 BeginInvoke的第一个参数为方法签名中的参数列表,第二个参数callback是当异步调用结束时自动回调的方法,第三个参数asyncState用于向第二个参数所确定的callback回调方法提供额外的信息。
B、 BeginInvoke方法返回一个IAsyncResult接口的对象。
Public interface IAsyncResult
{
Object AsyncState {get;}
WaitHandle AsyncWaitHandle { get;}
Bool CompletedSynchronously {get;}
Bool IsCompleted {get;}
}
C、 EndInvoke:发现异步调用完成时,它取出此异步调用方法执行的结果作为其返回值,如果异步调用方法有声明为ref和out的参数,它也负责填充它。
第3节 基于委托的异步编程模式的实践
1、 当异步调用完成之时,调用者线程如何知道调用的执行情况。
A、 使用轮询 如通过IAsyncResult对象的IsCompleted或AsyncWaitHandle实现。
B、 异步回调。
2、 处理异常调用中的异常。
需在EndInvoke方法所在的代码处捕获异步调用抛出的异常。
3、实现异步调用任务的同步问题。
第4节 实现IAsyncResult异步调用模式的组件
1、 在.NET基类型库中,有一些现有的组件直接实现了IAsyncResult异步调步模式,这些组件通常同时提供某个方法的同步与异步调用形式。
以WebRequest 为例。
IAsyncResult BeginGetResponse(AsyncCallback callback, object state) //异步
IAsyncResult BeginGetRequestStream(AsyncCallback callback, object state) //异步
Stream EndGetRequestStream(IAsyncResult asyncResult)
WebResponse EndGetResponse(IAsyncResult asyncResult)
Stream GetRequestStream() //同步
WebResponse GetResponse() //同步
2、 方法有如下特点:
A、凡有一个BeginXXX的,一定有一个“EndXXX”方法相对应。
B、每组“BeginXXX/EndXXX”,一定有一个对应的“XXX”同步方法。
C、“EndXXX”方法与对应的同步方法“XXX”的返回值类型相同。
D、“BeginXXX”返回一个IAsyncResult对象,而“EndXXX”方法的参数接收此对象。
3、此模式前基于委托的异步调用模式几乎一模一样,因此前面介绍的编程技巧可以继续使用。
第5节 基于事件的异步调用模式
1、 在.NET基类库中有部分组件实现了另一种异步模式,这就是基于事件的异步模式(Event-based Asynchronous Pattern),简称为EAP。
以WebClient 为例。
public void DownloadFileAsync(Uri address, string fileName);
public void DownloadFileAsync(Uri address, string fileName,object userToken);
public void CancelAsync(); //取消任务
2、 EAP有如下特点:
A、 实现了EAP的组件定义了以“Async”结尾的异步调用方法。
B、 当异步调用任务结束时,会激发一个相应的事件,事件的参数包含重要的信息。
如 WebClient会激发DownloadFileCompleted事件,参数信息存在 AsyncCompletedEventArgs对象中。
C、 实现了EAP的组件可能会提供一个用于取消异步任务的方法。
D、实现了EAP的组件提供一个向用户报告进度的事件。
如WebClient的 DownloadProgressChanged 事件。
3、【感】:用EAP组件原来是这么简单。
第6节 异步编程小结
1、 分类:异步编程分为 基于IAsyncResult的异步模式和基于事件的异步模式。而前者又分为基于委托的异步调用与使用类基类库中的组件两种。
2、 异步调用的每个方法都是独立的线程中执行的,其本质上就是一种多线程程序。
3、 适合场景:
A、 直接使用基类库中拥有异步调用特性的组件,如WebClient。
B、 需要在后台运行一些较耗费时间的任务,这些任务彼此相互独立,而且没有代码直接访问可视化的控件。
4、 不适合场景:
当在后台完成的工作有复杂的同步关系,或者必须访问共享的资源,不适合采用异步编程方法,而应直接应用多线程技 术或任务并行库来开发。