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. 〖Android〗ant build android project, setting android.jar precedence

    最近公司的一个项目中,新增了classes.jar包,与android.jar有冲突,必须得在加载android.jar前行加载classes.jar: 在持续集成环境中须使用ant编译,classe ...

  2. Xamarin.Android之SQLite.NET ORM

    一.前言 通过<Xamarin.Android之SQLiteOpenHelper>和<Xamarin.Android之ContentProvider>的学习,我们已经掌握了如何 ...

  3. python 模块之os.path模块

    # -*- coding: cp936 -*- #python 27 #xiaodeng #python 模块之os.path模块 #http://www.cnblogs.com/dkblog/arc ...

  4. java第六节 字符串/集合

    /* *String类和StringBuffer类 * 位于java.lang包中 * String类对象中的内容一旦被初始化就不能再改变 * StringBuffer类中用于封装内容可以改变的字符串 ...

  5. Liability

    Liability li·a·bil·i·ty  ˌlīəˈbilədē/   noun A person or thing whose presence or behavior is likely ...

  6. VS2017写的exe调用Delphi 7写的DLL

    公司有个很古老的系统,代码量很大,并且稳定线上运行10几年,这系统是公司的核心,公司收入基本靠它,系统几乎都是Delphi 7写的,要重写是不可能的.因为Delphi 7编译出来的DLL默认的导出符号 ...

  7. Android 百度鹰眼轨迹SDK(v2.1.6)

    闲聊 看过<鹰眼追击>这部电影的读者一定对"鹰眼"这台巨无霸计算机印象深刻,如今我们能够实现自己的鹰眼. 效果图 本篇为百度地图SDK第三篇博文 第一篇实现:Andro ...

  8. Git提交代码报错Git push error:src refspec XXX matches more than one解决方案

    Git提交代码push时,报错这个 error: src refspec master matches more than one. error: failed to push some refs t ...

  9. MySQL的keepalived高可用监控脚本

    MySQL的keepalived高可用监控脚本 MySQL(或者其它服务)的keepalived高可用监控脚本 开发脚本需求 :我们知道,keepalive是基于虚拟ip的存活来判断是否抢占maste ...

  10. windbg(1)

    1.http://www.cnblogs.com/huangyong9527/category/384128.html 2.http://www.cnblogs.com/pugang/category ...