那些年,我们一起学WCF--(6)PerCall实例行为

时间:2020-12-28 16:28:38

当客户端调用服务器端服务后,服务器端就会为客户端生成一个实例,关于服务实例的分配问题,在WCF中有专门的属性进行设置,可以让所有客户端共享一个实例,

也可以让一个客户端可以拥有多个实例,也可以让一个实例只能被客户端使用一次。

关于实例的分配和使用范围,在WCF通过服务行为的InstanceContextMode枚举进行设置.InstanceContextMode有三种枚举类型

PerSession=0 会话实例,此为默认值

PerCall=1

Single=2

接下来我们看下这三种策略的使用方法

1.PerCall实例

PerCall实例策略是指WCF为每个客户端的每一次请求,都会生成一个新的服务实例,各个实例不会相互影响,客户端调用结束后,服务器端立刻销毁该实例.

下面的这段代码演示了PerCall实例的实现,在服务器端的契约实现实现上用InstanceContextMode.PerCall标记为实例策略,

服务器端契约实现每调用一次AddCount方法,变量num的值会加1,当客户调用方法执行完毕的时候,会通过Dispose方法释放当前实例。

通过这个例子,我们可以看到,在客户端的服务代理调用两次AddCount方法,但是变量num的值没有改变,两次输出的值都是1

  1. [ServiceContract]
  2. publicinterface IPerCall
  3. {
  4. [OperationContract]
  5. int AddCount();
  6. }
  7. [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
  8. publicclass PerCallImpl:IPerCall,IDisposable
  9. {
  10. privateint num = 0;
  11. publicint AddCount()
  12. {
  13. num =num + 1;
  14. Console.WriteLine("当前值:"+num.ToString()+",时间:"+DateTime.Now.ToString());
  15. return num;
  16. }
  17. publicvoid Dispose()
  18. {
  19. Console.WriteLine("实例释放");
  20. Console.WriteLine("---------");
  21. }
 [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("---------");
}

启动服务器端,服务器端宿主是一个控制台应用程序

  1. ServiceHost host = new ServiceHost(typeof(PerCallImpl));
  2. host.Open();
  3. Console.WriteLine("服务器端启动...");
  4. Console.ReadLine();
  ServiceHost host = new ServiceHost(typeof(PerCallImpl));
host.Open();
Console.WriteLine("服务器端启动...");
Console.ReadLine();

在客户端,我们生成一个服务器端实例,同一个实例,调用服务器端的同一个方法两次,计数器的结果是一样的。

  1. privatevoid button1_Click(object sender, EventArgs e)
  2. {
  3. ChannelFactory<IPerCall> channelFactory = new ChannelFactory<IPerCall>("WSHttpBinding_IPerCall");
  4. IPerCall apple = channelFactory.CreateChannel();
  5. //同一个客户端实例调用AddCount方法两次,输出的结果一样
  6. apple.AddCount();
  7. apple.AddCount();
  8. }
   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();
}

效果图:

那些年,我们一起学WCF--(6)PerCall实例行为

通过这个例子,我们可以看到PerCall的优缺点

1.客户端每发送一次请求,服务器都会生成一个新的服务实例,各个服务实例不会相互影响,每次调用都可以看作一个单独的线程,不用考虑线程冲突的问题。不会产生并发性.

2.服务器端在客户端调用完毕后,就立刻释放服务实例,这样提高了服务器的使用率,在不用的时候立刻被释放,增加了系统的吞吐量,提高了服务器的使用率.

缺点:

假设我们要从数据库查询大数据量数据,每次调用查询的数据都是一样的,这是一个很耗时的过程,如果使用PerCall模式每次调用服务器端的方法都要查询一次数据,这样就增加了调用执行时间,客户端等待的时间就会过长,影响了客户端执行效率。这时候PerCall模式的弊端就暴露出来了,两次查询的数据不能共享。

对于这种问题,我们可以采用缓存进行解决,也可以使用其他实例行为进行解决,在下节我们看下其他实例行为。

demo下载:http://download.csdn.net/detail/zx13525079024/4596356