.Net中的几种异步模式

.Net中的几种异步模式

.Net中的几种异步模式
基于事件的异步模式(EAP)
IAsyncResult接口
简单的异步模式——引入lambda
Task
手动异步编程的问题

在C# 5.0引入async之前,存在几种异步编程模式,比如Event-based Asynchronous Pattern、IAsyncResult接口、Task等等。

基于事件的异步模式(EAP)

  1. private void DumpWebPage(Uri uri)
  2. {
  3. WebClient webClient = new WebClient();
  4. webClient.DownloadStringCompleted += OnDownloadStringCompleted;
  5. webClient.DownloadStringAsync(uri);
  6. }
  7. private void OnDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs eventArgs)
  8. {
  9. m_TextBlock.Text = eventArgs.Result;
  10. }

使用这种模式有点复杂,因为你不得不将一个简单的操作分成两个方法,还需要为完成事件指定一个EventArgs。上例中如果想要为WebClient增加其它请求,但是不想要已经注册的完成事件,那么上述的步骤还得再进行一遍。

IAsyncResult接口

  1. private void LookupHostName()
  2. {
  3. object unrelatedObject = "hello";
  4. Dns.BeginGetHostAddresses("oreilly.com", OnHostNameResolved, unrelatedObject);
  5. }
  6. private void OnHostNameResolved(IAsyncResult ar)
  7. {
  8. object unrelatedObject = ar.AsyncState;
  9. IPAddress[] addresses = Dns.EndGetHostAddresses(ar);
  10. // Do something with addresses
  11. ...
  12. }

这种模式解决了残留的事件处理函数,但是,它依然需要将一个简单操作分成两个方法。

基于事件的和基于IAsyncResult接口的异步编程模式都需要将一个操作分割成两个方法。而且都通过Object对象来传递参数,并且强制返回一个Object对象,这样会传递一些并不需要的数据。

简单的异步模式——引入lambda

如果不使用C# 5.0的async的话,将回调做为一个参数传递给方法可能是最简单的异步模式。

  1. void GetHostAddress(string hostName, Action<IPAddress> callback);

如果使用lambda表达式的话,可以直接将回调当做参数传递,而无需另外定义一个方法。

  1. private void LookupHostName()
  2. {
  3. int aUsefulVariable = 3;
  4. GetHostAddress("oreilly.com", address =>
  5. {
  6. // Do something with address and aUsefulVariable
  7. ...
  8. });
  9. }

这种模式的缺点是代码的可读性会受到影响。如果使用了多个异步API,可能会出现互相嵌套的lambda表达式。

注意:以上三种模式共同的缺点是任何异常都不会抛出给调用者来处理。而是通过调用异步操作结束方法(EndMethodName)或者获取Result属性来重新抛出异常。

Task

.NET 4.0引入了任务并行库(Task Parallel Library),其中最重要的类是Task和它的泛型类Task。使用Task可以实现异步编程:

  1. private void LookupHostName()
  2. {
  3. Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync("oreilly.com");
  4. ipAddressesPromise.ContinueWith(_ =>
  5. {
  6. IPAddress[] ipAddresses = ipAddressesPromise.Result;
  7. // Do something with address
  8. ...
  9. });
  10. }

使用ContinueWith方法来注册回调。

Task的优势是只需要一个Dns的方法,这使API变得很简洁。所有复杂的逻辑,包括异常处理和同步上下文都封装在Task类中。

手动异步编程的问题

上面的这些异步模式都可以称之为手动异步,它们存在两个共同的问题:

  1. 分割为两个方法。实际方法和回调方法。使用匿名方法或者lambda表达式缓解了这个问题,使代码看起来更加优雅一些,但同时也需要付出代码犬牙交错、难以跟踪的低价。
  2. 如果需要不只一个异步操作,甚至是需要循环调用异步操作,那么就不得不使用一个递归方法,和一个普通的循环相比更难以阅读。
  1. private void LookupHostNames(string[] hostNames)
  2. {
  3. LookUpHostNamesHelper(hostNames, 0);
  4. }
  5. private static void LookUpHostNamesHelper(string[] hostNames, int i)
  6. {
  7. Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync(hostNames[i]);
  8. ipAddressesPromise.ContinueWith(() =>
  9. {
  10. IPAddress[] ipAddresses = ipAddressesPromise.Result;
  11. // Do something with address
  12. ...
  13. if (i + 1 < hostNames.Length)
  14. {
  15. // 递归调用
  16. LookUpHostNamesHelper(hostNames, i + 1);
  17. }
  18. });
  19. }

来自为知笔记(Wiz)

时间: 2024-12-09 14:10:31

.Net中的几种异步模式的相关文章

.NET三种异步模式(APM、EAP、TAP)

APM模式: .net 1.0时期就提出的一种异步模式,并且基于IAsyncResult接口实现BeginXXX和EndXXX类似的方法. .net中有很多类实现了该模式(比如HttpWebRequest),同时我们也可以自定义类来实现APM模式(继承IAsyncResult接口并且实现BeginXXX和EndXXX方法) 1 /// <summary> 2 /// 异步 3 /// </summary> 4 /// <param name="sender"

Activity中的四种启动模式

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. Android总Activity的启动模式分为四种: [html] view plaincopy Activity启动模式设置: <activity android:name=".MainActivity" android:launchMode="standard" 

Android Activity中的四种启动模式

Android总Activity的启动模式分为四种: <activity android:name=".MainActivity" android:launchMode="standard" /> [standard]    默认模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中. [singleTop]    如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在

js中的4种函数调用模式

javascript一共有4种调用模式:函数调用模式.方法调用模式.构造器调用模式和间接调用模式. [1]函数调用模式 当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的.对于普通的函数调用来说,函数的返回值就是调用表达式的值 function add(x,y){ return x+y; } var sum = add(3,4); console.log(sum)//7 使用函数调用模式调用函数时,非严格模式下,this被绑定到全局对象:在严格模式下,this是undefined

VMware中的三种网络模式-----Host-only模式

3.Host-only模式(仅主机模式) Host-only模式:是一种封闭的网络模式,虚拟机只能与宿主机通过VMnet1进行通信.这种模式适合于在一个独立的环境中进行各种网络实验.这种模式与NAT模式的区别是没有地址转换服务,虚拟机只能访问到宿主机. 下面是一个关于Host-only使用的例子: ①虚拟机中编辑网络模式,选择Host-only模式: ②将虚拟机中网络连接的IP地址设置为: ③宿主机的VMnet1的网络连接IP设置为: ④网络拓扑图: 虚拟机通过VMNet1与宿主机进行通讯,但不

详解 Java 中的三种代理模式

代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.      这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法.      举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎

详解 Java 中的三种代理模式!

作者:岑宇 https://www.cnblogs.com/cenyu/p/6289209.html 代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法. 举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的

PLSQL中的三种参数模式IN、OUT、IN OUT

1.IN模式 IN模式是参数的默认模式,这种模式就是在程序运行的时候已经具有值,在程序体中值不会改变. 错误例子: 1 create or replace procedure in_proc ( 2 p_a in number , -- 形参, 这里的值是调用处传递的实参 3 p_b in number 4 )as 5 begin 6 p_a := 10 ; --实参被传递进来以后,在这个程序体中值就不可能被改变了 7 p_b := 20 ; 8 DBMS_OUTPUT.PUT_LINE(p_a

Vmware中的三种网络模式

安装好 VMware workstation 后,在物理机的网络连接里面你可以看到多了两块网卡: VMnet1 是虚拟机Host-only模式的网络接口 VMnet8 是虚拟机 NAT 模式的网络接口 1.桥接模式(Bridged) 桥接模式:桥接模式下,VMware虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问虚拟机局域网内的任何一台机器.不过你需要多于一个的IP地址,并且需要手工为虚拟系统配置IP地址.子网掩码,而且还要和宿主机器处于同一个网段,这样虚拟系统才能和宿主机器以及和