Welcome

首页 / 软件开发 / WCF / WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]

WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]2012-11-20 cnblogs Artech在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来讨轮另一种极端的服务实例上下文模式:单例(Single)模式。在单例模式下,WCF通过创建一个唯一的服务实例来处理所有的客户端服务调用请求。这是一个极端的服务实例激活方式,由于服务实例的唯一性,所有客户端每次调用的状态能够被保存下来,但是当前的状态是所有客户端作用于服务实例的结果,而不能反映出具体某个客户端多次调用后的状态。WCF是一个典型的多线程的通信框架,对并发的服务调用请求是最基本的能力和要求,但是服务实例的单一性就意味着相同服务实例需要在多个线程下并发地调用。

一、实例演示:演示服务实例的单一性

为了让读者对单例实例上下文模式有一个直观的认识,我们通过一个简单的案例演示单例模式下服务实例的单一性。这里使用前面章节使用过的累加器的例子,下面是服务契约和服务实现的定义:在初始化时,运算的结果为零,通过Add方法仅仅对结果累加,计算的结果通过GetResult操作返回。在CalculatorService上面,通过System.ServiceModel.ServiceBehaviorAttribute将服务设定为单例模式。

 1: using System.ServiceModel;
2: namespace Artech.WcfServices.Contracts
3: {
4: [ServiceContract(Namespace="http://www.artech.com/")]
5: public interface ICalculator
6: {
7: [OperationContract]
8: void Add(double x);
9: [OperationContract]
10: double GetResult();
11: }
12: }
1: using System.ServiceModel;
2: using Artech.WcfServices.Contracts;
3: namespace Artech.WcfServices.Services
4: {
5: [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
6: public class CalculatorService : ICalculator
7: {
8: private double _result;
9: public void Add(double x)
10: {
11: this._result += x;
12: }
13: public double GetResult()
14: {
15: return this._result;
16: }
17: }
18: }
在客户端,通过ChannelFactory<ICalculator>创建两个服务代理,模拟两个不同的客户端。从最终输出来看,得到的结果并不能反映出具体某个客户端正常的累加运算(对于通过calculator2模拟的客户端,仅仅调用了一次Add(3),得到的结果却是6)这是所有客户端一起累加的结果,这就是服务实例的单一性造成。

 1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
2: {
3: ICalculator calculator1 = channelFactory.CreateChannel();
4: ICalculator calculator2 = channelFactory.CreateChannel();
5:
6: Console.WriteLine("1st serivce proxy:");
7: Console.WriteLine("Add(3);");
8: calculator1.Add(3);
9: Console.WriteLine("The result is {0}. ", calculator1.GetResult());
10:
11: Console.WriteLine("2nd serivce proxy:");
12: Console.WriteLine("Add(3);");
13: calculator2.Add(3);
14: Console.WriteLine("The result is {0}.", calculator2.GetResult());
15: }
输出结果:

1st serivce proxy:
Add(3);
The result is 3.
2nd serivce proxy:
Add(3);
The result is 6.