博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

第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、 不适合场景:
      当在后台完成的工作有复杂的同步关系,或者必须访问共享的资源,不适合采用异步编程方法,而应直接应用多线程技  术或任务并行库来开发。