WCF 提供了三种实例上下文模式:PreCall、PreSession 以及 Single。开发人员通过 ServiceBehavior.InstanceContextMode 就可以很容易地控制服务对象的实例管理模式。而当 WCF 释放服务对象时,会检查该对象是否实现了 IDisposable 接口,并调用其 Dispose 方法,以便及时释放相关资源,同时也便于我们观察对象释放行为。

1. PreCall

在 PreCall 模式下,即便使用同一个代理对象,也会为每次调用创建一个服务实例。调用结束后,服务实例被立即释放(非垃圾回收)。对于不支持 Session 的 Binding,如 BasicHttpBinding,其缺省行为就是 PreCall。

[ServiceContract]
public interface IMyService
{
[OperationContract]
void Test();
} [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyServie : IMyService, IDisposable
{
public MyServie()
{
Console.WriteLine("Constructor:{0}", this.GetHashCode());
} [OperationBehavior]
public void Test()
{
Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);
} public void Dispose()
{
Console.WriteLine("Dispose");
}
} public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");
host.Open();
}); //----------------------- IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(),
new EndpointAddress("http://localhost:8080/MyService")); using (channel as IDisposable)
{
channel.Test();
channel.Test();
}
}
}

输出:
Constructor:30136159
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose
Constructor:41153804
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose

2. PreSession

PreSession 模式需要绑定到支持 Session 的 Binding 对象。在客户端代理触发终止操作前,WCF 为每个客户端维持同一个服务对象,因此 PreSession 模式可用来保持调用状态。也正因为如此,PreSession 在大并发服务上使用时要非常小心,避免造成服务器过度负担。虽然支持 Session 的 Binding 对象缺省就会启用 PreSession 模式,但依然建议你强制指定 SessionMode.Required 和 InstanceContextMode.PerSession。

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IMyService
{
[OperationContract]
void Test();
} [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyServie : IMyService, IDisposable
{
public MyServie()
{
Console.WriteLine("Constructor:{0}", this.GetHashCode());
} [OperationBehavior]
public void Test()
{
Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);
} public void Dispose()
{
Console.WriteLine("Dispose");
}
} public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");
host.Open();
}); //----------------------- IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(),
new EndpointAddress("http://localhost:8080/MyService")); using (channel as IDisposable)
{
channel.Test();
channel.Test();
}
}
}

输出:
Constructor:30136159
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Dispose

3. Single

一如其名,服务器会在启动时,创建一个唯一(Singleton)的服务对象。这个对象为所有的客户端服务,并不会随客户端终止而释放。

[ServiceContract]
public interface IMyService
{
[OperationContract]
void Test();
} [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyServie : IMyService, IDisposable
{
public MyServie()
{
Console.WriteLine("Constructor:{0}; {1}", DateTime.Now, this.GetHashCode());
} [OperationBehavior]
public void Test()
{
Console.WriteLine("Test:{0}; {1}", DateTime.Now, OperationContext.Current.SessionId);
} public void Dispose()
{
Console.WriteLine("Dispose:{0}", DateTime.Now);
}
} public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");
host.Open();
}); //----------------------- for (int i = 0; i < 2; i++)
{
IMyService channel = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(),
new EndpointAddress("http://localhost:8080/MyService")); using (channel as IDisposable)
{
channel.Test();
channel.Test();
}
}
}
}

输出:

Constructor:2007-4-17 17:31:01; 63238509
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;

还有另外一种方式来启动 Single ServiceHost。

AppDomain.CreateDomain("Server").DoCallBack(delegate
{
MyServie service = new MyServie(); ServiceHost host = new ServiceHost(service, new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");
host.Open();
});

此方式最大的好处是允许我们使用非默认构造,除此之外,和上面的例子并没有什么区别。

需要特别注意的是,缺省情况下,Single 会对服务方法进行并发控制。也就是说,多个客户端需要排队等待,直到排在前面的其他客户端调用完成后才能继续。看下面的例子。

[ServiceContract]
public interface IMyService
{
[OperationContract]
void Test();
} [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyServie : IMyService, IDisposable
{
public MyServie()
{
Console.WriteLine("Constructor:{0}", this.GetHashCode());
} [OperationBehavior]
public void Test()
{
Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);
Thread.Sleep(2000);
Console.WriteLine("Test End:{0}", OperationContext.Current.SessionId);
} public void Dispose()
{
Console.WriteLine("Dispose");
}
} public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");
host.Open();
}); //----------------------- for (int i = 0; i < 2; i++)
{
new Thread(delegate()
{
IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(),
new EndpointAddress("http://localhost:8080/MyService")); using (channel as IDisposable)
{
while (true)
{
channel.Test();
}
}
}).Start();
}
}
}

输出:
Constructor:63238509
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
...

我们可以通过修改并发模式(ConcurrencyMode)来改变这种行为,但需要自己维护多线程安全。

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
public class MyServie : IMyService, IDisposable
{
//...
}

输出:
Constructor:10261382
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09

WCF - 服务实例管理模式的更多相关文章

  1. WCF分布式开发步步为赢(9):WCF服务实例激活类型编程与开发

    .Net Remoting的激活方式也有三种:SingleTon模式.SingleCall模式.客户端激活方式,WCF服务实例激活类型包括三种方式:单调服务(Call Service),会话服务(Se ...

  2. UI层调用WCF服务实例(源码)

    WCF原理性的东西,暂时还没有深入研究,只是在公司的项目中使用到了,会调用,然后再多做了一些了解,现在将它抽出来了一个小实例,写了一个WCF的demo. 我写的这个WCF.Demo主要包括数据契约和服 ...

  3. WCF 项目应用连载[3] - 双向通信 实例管理与服务端监控

    WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序 第二节我们已经创建了Lig项目,并且能稳定工作了.现在我们来改进ILigAgent接口,实现WCF的双向通 ...

  4. [WCF编程]7.实例上下文模式

    一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...

  5. 跟我一起学WCF(8)——WCF中Session、实例管理详解

    一.引言 由前面几篇博文我们知道,WCF是微软基于SOA建立的一套在分布式环境中各个相对独立的应用进行交流(Communication)的框架,它实现了最新的基于WS-*规范.按照SOA的原则,相对独 ...

  6. WCF入门(九)--WCF实例管理

    这组由Windows通讯基础(WCF)结合一组消息(客户端请求)服务实例所采用的技术被称为实例管理.一个完全由三种类型实例激活支持WCF,它们如下所述. 1.每个调用服务 每次调用服务是Windows ...

  7. WCF 服务的集合管理器的设计

    今天是2019年2月1日,时间过得针对,马上就年底了,当前新年也离我们越来越近了.在此,我也祝福经常浏览我博客的朋友们“新年快乐.阖家欢乐”,来年有一个好彩头.在即将结束这一年之计,写今年的最后一片文 ...

  8. WCF实例管理的三种方式

    很多情况下,我们都需要控制wcf服务端对象的初始化方式,用来控制wcf实例在服务端的存活时间. Wcf框架提供了三种创建wcf实例的方式. WCF服务对象实例化基础 在普通的WCF请求和相应过程中,将 ...

  9. WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]

    原文:WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇] 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来 ...

随机推荐

  1. win10更新后无法远程,报 credssp加密oracle修正

    答案都在图里,看不清就浏览器放大观看 打开开始菜单,搜索“编辑组策略”  进入

  2. java.lang.IllegalArgumentException: Minimum column number is 0

    easyUI的datagrid导出Excel时报如下错误: [2018-06-20 15:00:21] [ERROR] [org.jeecgframework.poi.excel.export.Exc ...

  3. LUA返回的是引用

    ,} function t1.Show() print("t1 show") end function GetT() return t1 end local t2 = GetT() ...

  4. MATLAB 的 cell 大法(单元格数组)

    MATLAB 的 cell,称单元格数组 or 元胞数组:使用频率特别高,甚至比 struct 结构体还高. MATLAB文档给出的 cell 官方定义: A cell array is a coll ...

  5. Ubuntu中root用户和user用户的相互切换[转载自93度的饼干]

    Ubuntu中root用户和user用户的相互切换 Ubuntu是最近很流行的一款Linux系统,因为Ubuntu默认是不启动root用户,现在介绍如何进入root的方法. (1)从user用户切换到 ...

  6. Windbg使用方法

    hgy413的专栏 http://blog.csdn.net/hgy413/article/category/1143065

  7. HDU 4607 Park Visit (树的最长链)

    Park Visit Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. <welcome-file>index.action</welcome-file>直接设置action,404和struts2中的解决方案

    这几天的项目页面的访问全部改为.action访问,在修改首页时遇到了问题.将web.xml文件中<welcome-file>index.action</welcome-file> ...

  9. golang 学习笔记 ---Sizeof

    unsafe.Sizeof浅析 package main import "unsafe" import "fmt" func main() { slice := ...

  10. 使用Kotlin开发Android应用

    1.Kotlin介绍 [Kotlin](https://kotlinlang.org/) Kotlin是一门基于JVM的编程语言,它正成长为Android开发中用于替代Java语言的继承者.Java是 ...