WCF技术剖析之十一:异步操作在WCF中的应用(下篇)
原文:WCF技术剖析之十一:异步操作在WCF中的应用(下篇)
说完了客户端的异步服务调用(参阅WCF技术剖析之十一:异步操作在WCF中的应用(上篇)),我们在来谈谈服务端如何通过异步的方式为服务提供实现。在定义服务契约的时候,相信大家已经注意到了OperationContractAttribute特性具有一个bool类型的AsynPattern。该属性可以将一个服务操作定义成异步实现模式,接下来的内容主要是着眼于介绍异步操作的定义和实现原理。
一、异步操作的定义和实现原理
实现WCF异步服务操作模式在编程上具有一些限制:异步服务操作是通过两个配对的方法实现的,并且采用典型的异步操作命名方式:BeginXxx/EndXxx。两个方法需要采用如下的签名,指定了AsyncPattern属性的OperationContractAttribute只需要应用到BeginXxx方法上面。
1: [OperationContract(AsyncPattern = true)]
2: IAsyncResult BeginDoWork(parameters, AsyncCallback userCallback, object stateObject);
3: ReturnType EndDoWork(IAsyncResult asynResult);
比如下面两段代码可以看作相同的操作在同步和异步下的不同表现。
1: [OperationContract]
2: double Add(double x, double y);
1: [OperationContract(AsyncPattern = true)]
2: IAsyncResult BeginAdd(double x, double y, AsyncCallback userCallback, object stateObject);
3: double EndAdd(IAsyncResult asynResult);
理解了异步操作的定义模式之后,我们来谈谈WCF异步操作实现的原理。WCF通过类型OperationDescription表示对服务操作的描述。如下面的代码所示,OperationDescription具有3个重要的MemthodInfo类型的属性成员:SyncMethod、BeginMethod和EndMethod,分别表示同步方法、异步开始和结束方法。以上面的代码为例,如果采用SyncMethod表示Add方法,而BeginMethod和EndMethod对应于BeginAdd和EndAdd方法。
1: public class OperationDescription
2: {
3:
4: public MethodInfo SyncMethod { get; set; }
5: public MethodInfo BeginMethod { get; set; }
6: public MethodInfo EndMethod { get; set; }
7: //其他成员
8: }
WCF通过OperationSelector选择相应的操作,通过OperationInvoker执行被选择操作对应的方法。所有的OperationInvoker都实现了接口System.ServiceModel.Dispatcher.IOperationInvoker。下面是IOperationInvoker基本的定义。Invoke和InvokeBegin/InvokeEnd代表对操作同步和异步执行,IsSynchronous表示当前操作是否是异步的,如果操作的AsyncPattern为true则表明是异步操作。
1: public interface IOperationInvoker
2: {
3: object[] AllocateInputs();
4: object Invoke(object instance, object[] inputs, out object[] outputs);
5: IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state);
6: object InvokeEnd(object instance, out object[] outputs, IAsyncResult result);
7: bool IsSynchronous { get; }
8: }
在WCF中定义了两个典型的OperationInvoker:SyncOperationInvoker与AsyncOperationInvoker,它们分别用于同步操作和异步操作的执行。这两个OperationINvoker均实现了IOperationInvoker接口,SyncOperationInvoker实现了Invoke方法,AsyncOperationInvoker实现了InvokeBegin和InvokeEnd
当通过OperationSelector和InstanceProvider选出正确的方法和得到相应的服务实例的时候,WCF根据操作的AsyncPattern选择相应的OperationInvoker。如果是同步的则自然选择SyncOperationInvoker,执行Invoke方法。Invoke方法会通过OperationDescription的SyncMethod属性,得到同步操作方法的MethodInfo,采用反射的机制执行该方法;对于异步操作,则会调用AsyncOperationInvoker的InvokeBegin和InvokeEnd方法,InvokeBegin和InvokeEnd方法对应的MethodInfo通过OperationDescription的BeginMethod和EndMethod属性获得。得到相应的MethodInfo对象后,同样通过反射调用服务实例。
二、如何创建异步服务
在了解了异步操作的定义和具体的实现原理之后,我们通过一个简单的实例演示异步操作在WCF应用中的实现。本例子中,我们通过服务调用来读取服务端的文件,在实现文件读取操作的时候,采用异步文件读取方式。
先来看看服务契约的定义。服务契约通过接口IFileReader定义,基于文件名的文件读取操作以异步的方式定义在BeginRead和EndRead方法中。
1: using System;
2: using System.ServiceModel;
3: namespace Artech.AsyncServices.Contracts
4: {
5: [ServiceContract(Namespace="http://www.artech.com/")]
6: public interface IFileReader
7: {
8: [OperationContract(AsyncPattern = true)]
9: IAsyncResult BeginRead(string fileName, AsyncCallback userCallback, object stateObject);
10:
11: string EndRead(IAsyncResult asynResult);
12: }
13: }
FileReader实现了契约契约,在BeginRead方法中,根据文件名称创建FileStream对象,调用FileStream的BeginRead方法实现文件的异步读取,并直接返回该方法的执行结果:一个IAsyncResult对象。在EndRead方法中,调用FileStream的EndRead读取文件内容,并关闭FileStream对象。
1: using System;
2: using System.Text;
3: using Artech.AsyncServices.Contracts;
4: using System.IO;
5: namespace Artech.AsyncServices.Services
6: {
7: public class FileReaderService : IFileReader
8: {
9: private const string baseLocation = @"E:\";
10: private FileStream _stream;
11: private byte[] _buffer;
12:
13: #region IFileReader Members
14:
15: public IAsyncResult BeginRead(string fileName, AsyncCallback userCallback, object stateObject)
16: {
17: this._stream = new FileStream(baseLocation + fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
18: this._buffer = new byte[this._stream.Length];
19: return this._stream.BeginRead(this._buffer, 0, this._buffer.Length, userCallback, stateObject);
20: }
21:
22: public string EndRead(IAsyncResult ar)
23: {
24: this._stream.EndRead(ar);
25: this._stream.Close();
26: return Encoding.ASCII.GetString(this._buffer);
27: }
28:
29: #endregion
30: }
31: }
采用传统的方式寄宿该服务,并发布元数据。在客户端通过添加服务引用的方式生成相关的服务代理代码和配置。你将会发现客户端生成的服务契约和服务代理类中,会有一个唯一的操作Read。也就是说,不管服务采用同步模式还是异步模式实现,对客户端的服务调用方式没有任何影响,客户端可以任意选择相应的模式进行服务调用。
1: namespace Clients.ServiceReferences
2: {
3: [ServiceContractAttribute(ConfigurationName= "ServiceReferences.IFileReader")]
4: public interface IFileReader
5: {
6: [OperationContractAttribute(Action = " http://www.artech.com/IFileReader/Read", ReplyAction = " http://www.artech.com/IFileReader/ReadResponse")]
7: string Read(string fileName);
8: }
9:
10: public partial class FileReaderClient : ClientBase<IFileReader>, IFileReader
11: {
12:
13: public string Read(string fileName)
14: {
15: return base.Channel.Read(fileName);
16: }
17: }
18: }
直接借助于生成的服务代理类FileReaderClient,服务调用的代码就显得很简单了。
1: using System;
2: using Clients.ServiceReferences;
3: namespace Clients
4: {
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: using (FileReaderClient proxy = new FileReaderClient())
10: {
11: Console.WriteLine(proxy.Read("test.txt"));
12: }
13: Console.Read();
14: }
15: }
16: }
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
WCF技术剖析之十一:异步操作在WCF中的应用(下篇)的更多相关文章
- WCF技术剖析之十一:异步操作在WCF中的应用(上篇)
原文:WCF技术剖析之十一:异步操作在WCF中的应用(上篇) 按照操作执行所需的资源类型,我们可以将操作分为CPU绑定型(CPU Bound)操作和I/O绑定型(I/O Bound)操作.对于前者,操 ...
- WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成
原文:WCF技术剖析之七:如何实现WCF与EnterLib PIAB.Unity之间的集成 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅<MS Enterprise Li ...
- WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
原文:WCF技术剖析之十三:序列化过程中的已知类型(Known Type) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话) ...
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
原文:WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理 在前面一片文章(服务代理不能得到及时关闭会有什么后果?)中,我们谈到及时关闭服务代理(Service Proxy)在一个高并发环境 ...
- WCF技术剖析之二十一:WCF基本异常处理模式[中篇]
原文:WCF技术剖析之二十一:WCF基本异常处理模式[中篇] 通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultExcept ...
- WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经> ...
- WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇)
原文:WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在.NE ...
- WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制
原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service ...
- 《WCF技术剖析》博文系列汇总[持续更新中]
原文:<WCF技术剖析>博文系列汇总[持续更新中] 近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析(卷1)>的写作,一直无暇管理自己的Blog.在<WCF技术剖 ...
随机推荐
- dede修改移动文档的js
dede后台弹框修改: 想做个类似文章列表的移动功能,弹框,然后修改成功到表 先在list.js里复制一份moveArc的方法,到archives_do.php里复制一份moveArchives的方法 ...
- NAS简介
转自IBM资料库:https://community.emc.com/docs/DOC-15977 在20世纪80年代初,英国纽卡斯尔大学布赖恩.兰德尔教授 ( Brian Randell)和同事通过 ...
- XML 反序列化为Model
什么也不多说,直接贴代码 需要反序列的XML <?xml version='1.0' encoding='utf-8' ?> <GetCitiesListResponse> & ...
- 用SQL实现统计报表中的"小计"与"合计"的方法详解
本篇文章是对使用SQL实现统计报表中的"小计"与"合计"的方法进行了详细的分析介绍,需要的朋友参考下 客户提出需求,针对某一列分组加上小计,合计汇总.网上找 ...
- 转:.Net程序员学习Linux最简单的方法
有很多关于Linux的书籍,博客.大多数都会比较“粗暴“的将一大堆的命令塞给读者,从而使很多.NET程序员望而却步.未入其门就路过了. 所以我设想用一种更为平滑的学习方式, 就是在学习命令时,先用纯语 ...
- MFC自绘控件学习总结第二贴---转
首先感谢大家对第一帖的支持,应一些网友烈要求下面我在关于上一贴的一些补充和说明(老鸟可以无视)这一贴是实战+理论不知道第一帖的先看第一帖:http://topic.csdn.net/u/2011071 ...
- Tomcat7 + JRebel6.3.0 + IntelliJ idea 热部署配置过程+错误分析
以前使用Tomcat的时候直接就可以热部署,现在换了一个使用Spring框架的项目突然就不能热部署了. 网上说在tomcat里conf/context.xml中加入 <Context antiJ ...
- nginx学习六 高级数据结构之双向链表ngx_queue_t
1 ngx_queue_t简单介绍 ngx_queue_t是nginx提供的一个轻量级的双向链表容器,它不负责存储数据,既不提供数据的内存分配.它仅仅有两个指针负责把数据链入链表.它跟stl提供的qu ...
- ThinkPHP - 模板引擎
1.导入css/js文件 - CSS文件 <!--<link rel="stylesheet" type="text/css" href=" ...
- 使用SourceTree Push 出现 POST git-receive-pack (chunked) 的解决方法
在使用SourceTree上传资料的时候,遇到 POST git-receive-pack (chunked) 从 stackoverflow 看到这样一则 This is a bug in Git; ...