当客户端调用服务器端服务后,服务器端就会为客户端生成一个实例,关于服务实例的分配问题,在WCF中有专门的属性进行设置,可以让所有客户端共享一个实例,
也可以让一个客户端可以拥有多个实例,也可以让一个实例只能被客户端使用一次。
关于实例的分配和使用范围,在WCF通过服务行为的InstanceContextMode枚举进行设置.InstanceContextMode有三种枚举类型
PerSession=0 会话实例,此为默认值
PerCall=1
Single=2
接下来我们看下这三种策略的使用方法
1.PerCall实例
PerCall实例策略是指WCF为每个客户端的每一次请求,都会生成一个新的服务实例,各个实例不会相互影响,客户端调用结束后,服务器端立刻销毁该实例.
下面的这段代码演示了PerCall实例的实现,在服务器端的契约实现实现上用InstanceContextMode.PerCall标记为实例策略,
服务器端契约实现每调用一次AddCount方法,变量num的值会加1,当客户调用方法执行完毕的时候,会通过Dispose方法释放当前实例。
通过这个例子,我们可以看到,在客户端的服务代理调用两次AddCount方法,但是变量num的值没有改变,两次输出的值都是1
- [ServiceContract]
- publicinterface IPerCall
- {
- [OperationContract]
- int AddCount();
- }
- [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
- publicclass PerCallImpl:IPerCall,IDisposable
- {
- privateint num = 0;
- publicint AddCount()
- {
- num =num + 1;
- Console.WriteLine("当前值:"+num.ToString()+",时间:"+DateTime.Now.ToString());
- return num;
- }
- publicvoid Dispose()
- {
- Console.WriteLine("实例释放");
- Console.WriteLine("---------");
- }
[ServiceContract] public interface IPerCall { [OperationContract] int AddCount(); } [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)] public class PerCallImpl:IPerCall,IDisposable { private int num = 0; public int AddCount() { num =num + 1; Console.WriteLine("当前值:"+num.ToString()+",时间:"+DateTime.Now.ToString()); return num; } public void Dispose() { Console.WriteLine("实例释放"); Console.WriteLine("---------"); }
启动服务器端,服务器端宿主是一个控制台应用程序
- ServiceHost host = new ServiceHost(typeof(PerCallImpl));
- host.Open();
- Console.WriteLine("服务器端启动...");
- Console.ReadLine();
ServiceHost host = new ServiceHost(typeof(PerCallImpl)); host.Open(); Console.WriteLine("服务器端启动..."); Console.ReadLine();
在客户端,我们生成一个服务器端实例,同一个实例,调用服务器端的同一个方法两次,计数器的结果是一样的。
- privatevoid button1_Click(object sender, EventArgs e)
- {
- ChannelFactory<IPerCall> channelFactory = new ChannelFactory<IPerCall>("WSHttpBinding_IPerCall");
- IPerCall apple = channelFactory.CreateChannel();
- //同一个客户端实例调用AddCount方法两次,输出的结果一样
- apple.AddCount();
- apple.AddCount();
- }
private void button1_Click(object sender, EventArgs e) { ChannelFactory<IPerCall> channelFactory = new ChannelFactory<IPerCall>("WSHttpBinding_IPerCall"); IPerCall apple = channelFactory.CreateChannel(); //同一个客户端实例调用AddCount方法两次,输出的结果一样 apple.AddCount(); apple.AddCount(); }
效果图:
通过这个例子,我们可以看到PerCall的优缺点
1.客户端每发送一次请求,服务器都会生成一个新的服务实例,各个服务实例不会相互影响,每次调用都可以看作一个单独的线程,不用考虑线程冲突的问题。不会产生并发性.
2.服务器端在客户端调用完毕后,就立刻释放服务实例,这样提高了服务器的使用率,在不用的时候立刻被释放,增加了系统的吞吐量,提高了服务器的使用率.
缺点:
假设我们要从数据库查询大数据量数据,每次调用查询的数据都是一样的,这是一个很耗时的过程,如果使用PerCall模式每次调用服务器端的方法都要查询一次数据,这样就增加了调用执行时间,客户端等待的时间就会过长,影响了客户端执行效率。这时候PerCall模式的弊端就暴露出来了,两次查询的数据不能共享。
对于这种问题,我们可以采用缓存进行解决,也可以使用其他实例行为进行解决,在下节我们看下其他实例行为。
demo下载:http://download.csdn.net/detail/zx13525079024/4596356