华域联盟 .Net .NET中的异步编程-EAP/APM使用方法及案例介绍

.NET中的异步编程-EAP/APM使用方法及案例介绍

从.NET 4.5开始,支持的三种异步编程模式

•基于事件的异步编程设计模式 (EAP,Event-based Asynchronous Pattern)

•异步编程模型(APM,Asynchronous Programming Model)

•基于任务的编程模型(TAP,Task-based Asynchronous Pattern)

基于任务的异步模式 (TAP) 是基于 System.Threading.Tasks 命名空间的 Task 和 Task<TResult>,用于表示任意异步操作。 TAP 是新开发的建议异步设计模式,之后再讨论。


先总结一下旧有的2种模式:EAP、APM


从以下几个方面,看这2种异步编程方式的异同:

•命名、参数、返回值

•典型应用

•捕获异常

•状态

•取消操作

•进度报告

EAP

命名、参数、返回值

EAP的编程模式的代码命名有以下特点:

•将有一个或多个名为 “[方法名称]Async” 的方法。这些方法可能会创建同步版本的镜像,这些同步版本会在当前线程上执行相同的操作。

•该类还可能有一个 “[方法名称]Completed” 事件,监听异步方法的结果。

•它可能会有一个 “[方法名称]AsyncCancel”(或只是 CancelAsync)方法,用于取消正在进行的异步操作。

参数和返回值都没有特殊规定,按照业务需求而定

典型应用

以请求一个Url为例

复制代码 代码如下:

public class EAP_Typical

{

public static void AsyncRun()

{

Utility.Log("AsyncRun:start");

//测试网址

string url = http://sports.163.com/nba/;

using (WebClient webClient = new WebClient())

{

//获取完成情况

webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);

webClient.DownloadStringAsync(new Uri(url));

Utility.Log("AsyncRun:download_start");

}

}

static void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

{

string log = "AsyncRun:download_completed";

//获取返回结果

log += "|result_size=" + Utility.GetStrLen(e.Result);

Utility.Log(log);

}

}

捕获异常

异常信息一般在Completed的事件参数中传递的。紧接上面的例子,如果需要获取返回的异常信息,则需要改写一下DownloadStringComleted的方法。

复制代码 代码如下:

static void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

{

string log = "AsyncRun:download_completed";

if (e.Error != null) //可见,在事件的参数传输异常信息

{

//出现异常,就记录异常

log += "|error=" + e.Error.Message;

}

else

{

//没有出现异常,则记录结果

log += "|result_size=" + Utility.GetStrLen(e.Result);

}

Utility.Log(log);

}

状态

EAP本身并没有维护状态,如果需要的话,应该设置不同的时间响应不同的状态改变;

假设刚才的DownloadStringAsync,需要增加多几个状态值,可以考虑增加多几个事件。



Event DownloadStringStarted(响应下载刚开始)

Event DownloadStringPending(响应下载阻塞中)

Event DownloadStringCancel(响应下载取消时)

等等。

取消操作

按命名规范,如果操作对应有“[方法名称]AsyncCancel”(或只是 CancelAsync)方法,则支持取消操作。

取消的状态捕获,还是以刚才的下载Url输出html为例,还是在DownloadStringCompleted 获取取消与否的状态。DownloadStringCompletedEventArgs. Cancelled

注意的是,如果用户执行了CancelAsync后,在DownloadStringCompletedEventArgs.Error就会获取到对应的异常,此时不要再取DownloadStringCompletedEventArgs.Result。

进度报告

EAP没有硬性规定说要支持进度报告,但可以很顺其自然地通过时间响应进度变化。

以当前例子,WebClient 就提供了DownloadProgressChanged 做进度变化的响应事件。

APM

命名、参数、返回值

APM的编程模式的代码命名有以下特点:

•使用 IAsyncResult 设计模式的异步操作是通过名为[Begin操作名称] 和 [End操作名称] 的两个方法来实现的,这两个方法分别开始和结束异步操作 操作名称。 例如,FileStream 类提供 BeginRead 和 EndRead 方法来从文件异步读取字节。 这两个方法实现了 Read 方法的异步版本。

•在调用 [Begin操作名称] 后,应用程序可以继续在调用线程上执行指令,同时异步操作在另一个线程上执行。 每次调用 [Begin操作名称] 时,应用程序还应调用 [End操作名称] 来获取操作的结果。

典型应用

以请求一个Url为例

复制代码 代码如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net;

using System.IO;

namespace AsyncTest1.APM

{

public class APMTestRun1

{

public static void AsyncRun()

{

Utility.Log("APMAsyncRun:start");

//测试网址

string url = "http://sports.163.com/nba/";

HttpWebRequest webRequest = HttpWebRequest.Create(url) as HttpWebRequest;

webRequest.BeginGetResponse(Callback, webRequest);

Utility.Log("AsyncRun:download_start");

}

private static void Callback(IAsyncResult ar)

{

var source = ar.AsyncState as HttpWebRequest;

var response = source.EndGetResponse(ar);

using (var stream = response.GetResponseStream())

{

using (var reader = new StreamReader(stream))

{

string content = reader.ReadToEnd();

Utility.Log("AsyncRun:result_size=" + Utility.GetStrLen(content));

}

}

}

}

}

委托的异步调用也用的是APM模式,这个方式的强大之处,在于可以使任何方法编程异步调用。

复制代码 代码如下:

/// <summary>

/// 一个耗时的方法

/// </summary>

private static void CaluateManyNumber() {

for (int i = 0; i < 10; i++)

{

Thread.Sleep(100);

Console.WriteLine("loop==>"+i.ToString());

}

}

/// <summary>

/// 委托,让耗时方法可以异步执行

/// </summary>

public static void AsyncDelegate() {

//委托简单的包装了一下方法

Action action = CaluateManyNumber;

action.BeginInvoke(DelegateCallback, null);

Console.WriteLine("action begin");

}

/// <summary>

/// 异步回调

/// </summary>

/// <param name="ar"></param>

private static void DelegateCallback(IAsyncResult ar) {

AsyncResult asyncResult = ar as AsyncResult;

var delegateSource = asyncResult.AsyncDelegate as Action;

delegateSource.EndInvoke(ar);

Console.WriteLine("action end");

}

捕获异常

异常信息要在[End操作名称]中获取。

复制代码 代码如下:

private static void Callback(IAsyncResult ar)

{

var source = ar.AsyncState as HttpWebRequest;

WebResponse response = null;

try

{

response = source.EndGetResponse(ar);

}

catch (Exception ex) {

Utility.Log("error:" + ex.Message);

response = null;

}

if (response != null)

{

using (var stream = response.GetResponseStream())

{

using (var reader = new StreamReader(stream))

{

string content = reader.ReadToEnd();

Utility.Log("AsyncRun:result_size=" + Utility.GetStrLen(content));

}

}

}

}

状态和取消操作、进度报告

APM模式本身不支持状态多样化和取消操作、进度报告。

您可能感兴趣的文章:

  • 深入分析C#异步编程详解
  • 高效的.Net UDP异步编程实现分析
  • .net4.5使用async和await异步编程实例

本文由 华域联盟 原创撰写:华域联盟 » .NET中的异步编程-EAP/APM使用方法及案例介绍

转载请保留出处和原文链接:https://www.cnhackhy.com/46181.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部