WCF - 服务实例管理模式
发布日期:2021-06-29 03:54:14
浏览次数:2
分类:技术文章
本文共 7396 字,大约阅读时间需要 24 分钟。
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:30136159Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4DisposeConstructor:41153804Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4Dispose2. PreSessionPreSession 模式需要绑定到支持 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:30136159Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847aTest:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847aDispose3. 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; 63238509Test: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:63238509Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfcTest End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfcTest:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfcTest End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfcTest:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfcTest End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc...我们可以通过修改并发模式(ConcurrencyMode)来改变这种行为,但需要自己维护多线程安全。 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)] public class MyServie : IMyService, IDisposable { //... }
输出:Constructor:10261382Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3cTest End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09... 转载地址:https://blog.csdn.net/zengjibing/article/details/3812513 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关注你微信了!
[***.104.42.241]2024年04月25日 17时23分35秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
记一次django项目的部署
2019-04-29
测试项目调研
2019-04-29
接手软件测试新项目的流程
2019-04-29
jmeter-性能测试2-脚本录制开发
2019-04-29
jmeter-性能测试3-参数化
2019-04-29
期货基础知识
2019-04-29
期权基础
2019-04-29
jmeter-性能测试6-性能基础扫盲
2019-04-29
pytest+allure生成测试报告
2019-04-29
接口测试用例
2019-04-29
vnc安装配置
2019-04-29
Allure 测试报告:allure.title 去掉后方的参数化显示
2019-04-29
appium起源-环境配置
2019-04-29
appium初识-firstdemo
2019-04-29
allure报告的定制化
2019-04-29
Python爬虫实战:批量下载网站图片
2019-04-29
Python 使用 PyQt5 开发的关机小工具分享
2019-04-29
利用Python爬取微博数据生成词云图片实例代码
2019-04-29
对Python3 解析html的几种操作方式小结
2019-04-29
Python基于opencv调用摄像头获取个人图片的实现方法
2019-04-29