异步编程模式

突然在园子里看到关于异步编程的演变,搜了一下MSDN,开年工作量比较大,有空再回来总结

 

.NET framework 为执行异步操作提供三种模式:

  • 异步编程模型 (APM) 模式(也称为 IAsyncResult 模式),其中异步操作要求 Begin 和 End 方法(例如,异步写操作的 BeginWrite 和 EndWrite)。 对于新的开发工作不再建议采用此模式。(不支持对异步操作的取消和没有提供对进度报告的功能有关更多信息,请参见异步编程模型 (APM)

  • 基于事件的异步模式 (EAP) 需要一个具有 Async 后缀的方法,还需要一个或多个事件、事件处理程序、委托类型和 EventArg 派生的类型。 EAP 是在 .NET Framework 2.0 版中引入的。 对于新的开发工作不再建议采用此模式。 有关更多信息,请参见基于事件的异步模式 (EAP)

  • 基于任务的异步模式 (TAP),该模式使用一个方法表示异步操作的启动和完成。 .NET Framework 4 中引入了 TAP,并且是 .NET Framework 中异步编程的建议方法。 有关更多信息,请参见基于任务的异步模式 (TAP)

 

基于任务的异步模式 (TAP)使用单个方法表示异步操作的开始和完成。 这与异步编程模型 (APM 或 IAsyncResult)模式相反(该模式要求 Begin 和 End 方法),以及与基于事件的异步模式 (EAP) 相反(该模式要求具有 Async 后缀的方法,还要求一个或多个事件、事件处理程序委托类型和 EventArg 派生类型)。 在 TAP 的异步方法在操作名称后面包括 Async 后缀;例如,获取操作的 GetAsync 如果您正在添加 TAP 方法到已包含具有 Async 后缀的方法名称的类,请改用该后缀TaskAsync 例如,如果类具有 GetAsync 方法,请使用名称 GetTaskAsync

TAP 方法返回 Task 或 Task<TResult>,基于相应的同步方法是否返回 void 或类型 TResult

TAP 方法的参数应与其同步副本的参数匹配,并应以相同顺序提供。但是,out 和 ref 参数不受此规则的限制,并应完全避免。 将通过 out 或 ref 参数返回的任何数据均应改为作为 Task<TResult> 返回的 TResult 的一部分,应使用元组或自定义数据结构以容纳多个值。 方法是纯专用于任务的创建、进程或组合(其中方法的异步目的很有把握在方法名称或的方法生命周期)的类型的名称不需要遵循上面的名称模式;此类方法通常称为 组合器 组合器的示例包括 WhenAll 和 WhenAny,并且在文章使用基于任务的异步模式使用内置基于任务的组合器节讨论。

 

  •  任务状态:

Task 类用于异步操作提供一个生命周期,并且,该循环由 TaskStatus 枚举表示。 若要支持从 Task 和 Task<TResult>派生的角用例类型和支持构造的分离计划的,Task 选件类公开 Start 方法。 其公共 Task 构造函数创建的任务被称为冷任务,因为他们在非安排的 Created 状态开始其生命周期,仅在这些实例上调用了Start 时才进行安排。 所有其他任务在热状态下开始其生命周期,这意味着它们表示的异步操作已启动,并且其任务状态是 TaskStatus.Created 以外的枚举值。 从 TAP 方法返回的所有任务必须激活。 如果 TAP 方法在内部使用任务的构造函数来实例化要返回的任务,那么该 TAP 方法必须在返回之前在 Task 对象上调用 StartTAP 方法的使用者可以安全地假设返回的任务处于活动状态并且不应尝试对 TAP 方法返回的任何 Task 调用 Start 在活动的任务上调用 Start 将引发InvalidOperationException 异常。

  • 任务取消:

TAP 中的取消是异步方法实现者和异步方法使用者的选项。 如果操作允许取消,则它显示接受取消标记的异步方法的重载(CancellationToken 实例)。 按照约定,该参数命名为 cancellationToken

public Task ReadAsync(   byte [] buffer, int offset, int count,  CancellationToken cancellationToken);

该异步操作监视取消请求的此标记。 如果它收到取消请求,则可以选择接受该请求和取消操作。 如果取消请求导致过早地结束工作,则 TAP 方法返回一个在Canceled 状态结束的任务;不引发可用的结果和异常。该 Canceled 状态被视为与 Faulted 和 RanToCompletion 状态最后(完成的)任务的状态。 因此,如果一个任务在 Canceled 状态中,则其 IsCompleted 属性返回 true 在 Canceled 状态下完成任务时,对使用任务注册的任一持续性进行计划或执行,除非持续选项,如指定取消持久性 NotOnCanceled 任何通过使用语言功能异步等待已取消的任务的代码都将继续执行但不接收 OperationCanceledException 或其中派生的异常。 通过诸如 Wait 的方法同步阻止的代码等待任务,并 WaitAll 也继续具有异常的运行。

如果取消标记请求在接受调用标记的 TAP 方法之前取消,TAP 方法应返回 Canceled 任务。但是,如果在运行异步操作时请求取消,该异步操作不需要接受该取消请求。仅当该操作如取消请求的结果那样结束,返回的任务才应以 Canceled 状态结束。 如果已请求取消,但仍然生成了结果或异常,则任务应在 RanToCompletion或 Faulted 状态中结束。 对于希望首先进行取消的开发人员使用的异步方法,您不需要提供不接受取消标记的重载。对于不可取消的方法,不要提供接受取消的重载;这有助于向调用方指示目标方法是否真正可取消。不要求取消的使用者代码可以调用接受 CancellationToken 的方法,并提供 None 作为参数值。 None 功能上等效于默认 CancellationToken

  •  进度报告:

 

某些异步操作受益于提供进度通知;这些通常用于都会用相关信息更新的用户界面有关该异步操作的进度。 在 TAP 中,处理进度通过 IProgress<T> 接口,传递给异步方法作为通常名为 progress 的参数。调用异步方法时提供进度接口有助于消除调用操作可能缺少更新后事件处理程序不正确注册情况下不正确使用导致的争用情况。更重要的是,根据所使用的代码进度界面将支持不同的进度实现。例如,使用代码可能只关心最近的进展情况,可能缓冲所有更新,可能需要为各个更新调用操作,也可能需要控制是否需将该调用封送到特定线程。 通过使用接口的不同的实现,所有这些选项都可以达到自定义特定的使用者需要。仅当 API 支持进度通知,与取消,TAP 实现应提供 IProgress<T> 参数。 例如,如果本文前面所述的 ReadAsync 方法可以以到目前为止读取的字节数的形式报告中间进度,进度回调可能为IProgress<T> 接口:

 

 
public Task ReadAsync(
    byte [] buffer, int offset, int count, 
    IProgress<long> progress);

 

如果 FindFilesAsync 方法返回满足特定搜索模式的所有文件的列表,那么进度回调就可以对已完成工作的百分比以及当前部分结果集进行估计。可使用元组执行此操:

 

 
public Task<ReadOnlyCollection<FileInfo>> FindFilesAsync(
    string pattern, 
    IProgress<Tuple<double,ReadOnlyCollection<List<FileInfo>>>> progress);

 

或具有特定于 API 的数据类型:

 

 
public Task<ReadOnlyCollection<FileInfo>> FindFilesAsync(
    string pattern, 
    IProgress<FindFilesProgressInfo> progress);

 

在后一种情况下,特殊数据类型应该加上后缀 ProgressInfo

 

如果 TAP 实现提供接受 progress 参数的重载,它们必须允许该参数成为 null,在这种情况下,不会报告任何进度。 分接头实现如何在何处同步进度到 Progress<T>对象报告,使该异步方法快速提供进度,并允许进度的使用者确定最好处理信息。 例如,进度实例可以选择将回调封送,并引发有关捕获到的同步上下文的事件。

 

 

 

地址:http://msdn.microsoft.com/zh-cn/library/jj152938(v=vs.110).aspx

posted @ 2014-02-13 15:56  我不是杰克船长  阅读(241)  评论(0编辑  收藏  举报