并发与实例上下文模式: WCF服务在不同实例上下文模式下的并发表现2012-07-15 博客园 Artech由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的,所以在不同的实例上下文模式下,会表现出不同的并发行为。接 下来,我们从具体的实例上下文模式的角度来剖析WCF的并发,如果对WCF实例上下文模式和实例上下文提供机制不了解的话,请参阅《WCF 技术剖析(卷1)》第9章。在《实践重于理论》一文中,我写一个了简单的WCF应用,通过这个应用我们可以很清楚了监控客户端和服务操作的执行情况下。借此 ,我们可以和直观地看到服务端对于并发的服务调用请求,到底采用的是并行还是串行的执行方式。接下来,我们将充分地利用这个监控 程序,以实例演示加原理分析相结合的方式对不同实例上下文模式下的并发实现机制进行深度剖析。一、单调(PerCall)实例上下文模式由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的,但是对单调的实例上下文模式,WCF服务端运行时总是创建一个 全新的InstanceContext来处理每一个请求,不管该请求是否来自相同的客户端。所以在单调实例上下文模式下,根本就不存在对某个 InstanceContext的并发调用的情况发生。我们可以通过我们监控程序来验证这一点。为此,我们需要通过ServiceBehaviorAttribute将实例上下文模式设置成 InstanceContextMode.PerCall,相关的代码如下所示。
1: [ServiceBehavior(UseSynchronizationContext = false,InstanceContextMode = InstanceContextMode.PerCall)]
2: public class CalculatorService : ICalculator
3: {
4: //省略成员
5: }
下面是客户端进行并发服务调用的代码:
1: for (int i = 1; i <= 5; i++)
2: {
3: ThreadPool.QueueUserWorkItem(state =>
4: {
5: int clientId = Interlocked.Increment(ref clientIdIndex);
6: ICalculator proxy = _channelFactory.CreateChannel();
7: using (proxy as IDisposable)
8: {
9: EventMonitor.Send(clientId, EventType.StartCall);
10: using (OperationContextScope contextScope = new OperationContextScope(proxy as IContextChannel))
11: {
12: MessageHeader<int> messageHeader = new MessageHeader<int>(clientId);
13: OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader.GetUntypedHeader(EventMonitor.CientIdHeaderLocalName, EventMonitor.CientIdHeaderNamespace));
14: proxy.Add(1, 2);
15: }
16: EventMonitor.Send(clientId, EventType.EndCall);
17: }
18: }, null);
19: }
如果在此基础上运行我们的监控程序,将会得到如图1所示的输出结果,从中我们可以看出,仍然我们采用默认的并发模式 (ConcurrencyMode.Single),来自5个不同客户端(服务代理)的调用请求能够及时地得到处理。

图1 单调实例上下文模式下的并发事件监控输出(不同客户端)