zoukankan      html  css  js  c++  java
  • WCF中的AsyncPattern

    WCF中的AsyncPattern

     

    (系列博文源自 http://pfelix.wordpress.com/,由笔者翻译并整理,转载请注明)

    在wcf 的 service contract中, 服务接口方法定义都要求有 operation context这个标签。 在这个标签里有一个 AsyncPattern的属性用以定制 service的异步模型。

    考虑如下接口定义:

    复制代码
    1: [ServiceContract]   
    2: interface IService {   
    3:     [OperationContract]   
    4:     ReplyData Operation1(RequestData rd);   
    5:    
    6:     [OperationContract(AsyncPattern = true)]   
    7:     IAsyncResult BeginOperation2(RequestData rd, AsyncCallback ac, object obj);   
    8:     ReplyData EndOperation2(IAsyncResult ar);   
    9: }
    复制代码
    • 第一个服务方法定义中, AsyncPattern默认为false。 这是一个简单的 request-response方法 'Operation1'. 在默认设置下,这个方法由server端同步实现。 具体过程是由 WCF Dispatcher调用这个方法,生成传入参数,在这个方法执行过程中会占用这个service线程,最终返回reply,并由wcf生成返回消息传回客户端。
    • 第二个服务方法定义中, AsyncPattern设成true,同样定义了一个request-response方法 'Operation2'。然而, 这个方法实现要求是一个包含两个方法:BeginOperation2, EndOperation2的异步实现。在这里的‘异步’ 意味着
      • WCF dispatcher 调用 BeginOperation2 , 生成传入参数和一个异步回调, 还有一些状态信息。
      • 这个方法开始执行并最终返回一个IAsyncResult
      • 当这个方法执行结束时会调用AsyncCallback 。
      • 这个AsyncCallback 是由wcf实现 会接下来调用 EndOperation2 收集返回值并把消息传回给客户端。     

    需要注意的是,即使设置了AsyncPattern, 在通信层面而言这个service依然是一个 request-response 模型。 这个异步只是service 的实现细节。 参考生成的wsdl定义:  

    复制代码
    1: <wsdl:portType name="IService">   
    2:     
    3:   <wsdl:operation name="Operation1">   
    4:     <wsdl:input wsaw:Action="..." message="..." />    
    5:     <wsdl:output wsaw:Action="..." message="..." />    
    6:   </wsdl:operation>   
    7:     
    8:   <wsdl:operation name="Operation2">   
    9:     <wsdl:input wsaw:Action="..." message="..." />   
    10:     <wsdl:output wsaw:Action="..." message="..." />   
    11:   </wsdl:operation>  
    12:    
    13: </wsdl:portType>
    复制代码

    这并不会改变service的通信模型,有别于普遍意义上的 “异步服务”。

    那么,这种实现方式有什么意义? 或者说在何种场景下应该使用这种实现方式?

    砖家说,当服务实现中会长时间block住当前服务线程时就应该考虑这种实现方式。

    结合上图应该能比较容易理解这种方式带来的优势, 在上图的例子中这种实现方式能在开始 io前释放服务线程, 并在 io结束后重新获得一个线程做后续操作。

    理论上来说这种方式就不会存在一个‘被阻塞’的线程,以节约线程资源来提升service并发。

    最后提一下在client端这个属性的作用。

    当使用 svcutil.exe时加上 /async 会生成以下服务器代理接口定义:

    复制代码
    1: public interface IService {   
    2:        
    3:     // Operation 1 synchronous method      
    4:     [System.ServiceModel.OperationContractAttribute(Action=".../Operation1", ReplyAction=".../Operation1Response")]   
    5:     ReplyData Operation1(RequestData rd);   
    6:     
    7:     // Operation 1 asynchronous method pair            
    8:     [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action=".../Operation1", ReplyAction=".../Operation1Response")]   
    9:     System.IAsyncResult BeginOperation1(RequestData rd, System.AsyncCallback callback, object asyncState);          
    10:     ReplyData EndOperation1(System.IAsyncResult result);  11:           
    12:     // Operation 2 synchronous method     
    13:     [System.ServiceModel.OperationContractAttribute(Action=".../Operation2", ReplyAction=".../Operation2Response")]  
    14:     ReplyData Operation2(AsyncPattern.Client.AsyncClient.RequestData rd);
    15:           
    16:     // Operation 2 asynchronous method pair           
    17:     [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action=".../Operation2", ReplyAction=".../Operation2Response")] 
     18:     System.IAsyncResult BeginOperation2(RequestData rd, System.AsyncCallback callback, object asyncState);          
    19:     ReplyData EndOperation2(System.IAsyncResult result);  20:       
    21: }
    复制代码

    如果理解了一开始的部分,很容易想到这根服务器端的实现方式无关。 这只是客户端的一种内部实现方式。

    其效果就是调用服务器时会立刻返回(而不阻塞),再由调用EndOperation的形式得到执行结果。

    值得一提的是类似的效果虽然可以通过多线程来实现。 但依然不会有wcf Async机制高效, 因为wcf 的异步模型是基于通信层支持, 并不会阻塞任何一个线程。而多线程实现依然会阻塞线程池中的异步线程。

    (译者:多数情况而言在客户端这点优势倒没啥意义。。。。)

  • 相关阅读:
    修复PLSQL Developer 与 Office 2010的集成导出Excel 功能
    Using svn in CLI with Batch
    mysql 备份数据库 mysqldump
    Red Hat 5.8 CentOS 6.5 共用 输入法
    HP 4411s Install Red Hat Enterprise Linux 5.8) Wireless Driver
    变更RHEL(Red Hat Enterprise Linux 5.8)更新源使之自动更新
    RedHat 5.6 问题简记
    Weblogic 9.2和10.3 改密码 一站完成
    ExtJS Tab里放Grid高度自适应问题,官方Perfect方案。
    文件和目录之utime函数
  • 原文地址:https://www.cnblogs.com/raohuagang/p/3553570.html
Copyright © 2011-2022 走看看