Learning WCF:Life Cycle of Service instance
示例代码下载地址:WCFDemo1Day
概述
客户端向WCF服务发出请求后,服务端会实例化一个Service对象(实现了契约接口的对象)用来处理请求,实例化Service对象以及维护其生命周期的方式在WCF中共有三种不同的类型,分别是:
- Per-Call
- Per-Session
- Single
程序中通过设置ServiceBehavior特性来指定,如下:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CommService : ICommContract
{
}
这是枚举InstanceContextMode的内容:
public enum InstanceContextMode
{
PerSession = 0,
PerCall = 1,
Single = 2,
}
Per-Call
每次调用服务端服务端方法,服务端都会实例化一个对象来处理请求,为观察结果,现编写如下代码:
服务类:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CommService : ICommContract
{
public CommService()
{
Console.WriteLine("构造函数被执行");
}
public int Add(int a, int b)
{
Console.WriteLine("Add被调用,Thread:" + Thread.CurrentThread.ManagedThreadId + " fromPool:" + Thread.CurrentThread.IsThreadPoolThread);
return a + b;
}
public void Dispose()
{
Console.WriteLine("对象销毁");
Console.WriteLine("_____________________________");
}
public void SendStr(string str)
{
Console.WriteLine("SendStr被调用,Thread:" + Thread.CurrentThread.ManagedThreadId + " fromPool:" + Thread.CurrentThread.IsThreadPoolThread);
}
}
如果服务类实现了接口IDisposable
,当服务类被销毁时会回调Dispose
方法,可以在Dispose
方法中写一些WriteLine语句以观察对象的生命周期。
客户端代码:
class Program
{
static void Main(string[] args)
{
CommService.CommContractClient client = new CommService.CommContractClient();
client.SendStr("hello");
client.SendStr("hello");
client.SendStr("hello");
client.Close();
}
}
运行效果:
Per-Session
InstanceContextMode
被设置为PerSession
后,同一个客户端多次调用一个远程Web服务方法时,服务端只会实例化一次,修改上面的服务端代码第一行如下:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
再看运行效果:
上面的实例代码所使用的绑定模式为WSHttpBinding
,如果使用BasicHttpBinding
的话,即使是指定了InstanceContextMode
为PerSession
服务端也不会保存会话,现将支持Per-Session
的绑定方式列举如下:
WSXXXBinding(with Message security or reliability)
NetTcpXXXBinding
NetXXXPipeBinding
后两个容易理解,第一个括号里什么什么玩意儿,请看宿主代码:
class Program
{
static void Main(string[] args)
{
Uri baseURI = new Uri("http://localhost:8000/Services");
ServiceHost host = new ServiceHost(typeof(CommService), baseURI);
try
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(ICommContract), binding, "CommonService");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetUrl = new Uri("http://localhost:8080/Services");
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
host.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
host.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
host.Abort();
}
}
}
binding.Security.Mode
默认为Message
,现在把它改成None
再运行程序:
哈,虽然InstanceContextMode
设置为了Per-Session
,实际上还是Per-Call
,这部分内容和安全性有关,希望我有时间以后会写到吧,今天暂时不去研究。
除了绑定方式,还有一个地方也影响到了Per-Session
是否起作用,它是契约接口特性ServiceContract
的属性SessionMode
,该枚举内容如下:
public enum SessionMode
{
Allowed = 0,
Required = 1,
NotAllowed = 2,
}
SessionMode
属性默认是Allowed
,如果设置为Required
表示必须启用会话模式,NotAllowed
表示必须不能启动会话模式,Allowed
表示无所谓。谁有兴趣可以一一尝试。现将契约接口的特性改成如下:
[ServiceContract(Namespace = "zzy0471.cnblogs.com.CommService", SessionMode = SessionMode.NotAllowed)]
public interface ICommContract : IDisposable
{
[OperationContract()]
int Add(int a, int b);
[OperationContract()]
void SendStr(String str);
}
再运行程序:
虽然InstanceContextMode
设置为了Per-Session
,实际上还是Per-Call
。
此外,还有一个需要注意的地方,如果在方法契约特性中设置属性IsTerminating
为true
,如下图
[OperationContract(IsTerminating = true)]
void SendStr(String str);
运行服务端会导致运行时错误,IsTerminating
设置为了true
和Per-Session
模式相矛盾,IsTerminating
的意思是:“获取或设置一个值,该值指示服务操作在发送答复消息(如果存在)后,是否会导致服务器关闭会话”
Per-Single
InstanceContextMode
被设置为PerSingle
后,所有的客户端请求都只有一个服务端实例对象来处理,服务启动时对象创建,服务关闭时对象销毁。现修改InstanceContextMode
特性如下:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class CommService : ICommContract
{
public CommService()
{
Console.WriteLine("构造函数被执行");
}
public int Add(int a, int b)
{
Console.WriteLine("Add被调用,Thread:" + Thread.CurrentThread.ManagedThreadId + " fromPool:" + Thread.CurrentThread.IsThreadPoolThread);
return a + b;
}
public void Dispose()
{
Console.WriteLine("对象销毁");
Console.WriteLine("_____________________________");
}
public void SendStr(string str)
{
Console.WriteLine("SendStr被调用,Thread:" + Thread.CurrentThread.ManagedThreadId + " fromPool:" + Thread.CurrentThread.IsThreadPoolThread);
}
}
为了方便观察,修改客户端代码,以模拟多个客户端:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
CommService.CommContractClient client = new CommService.CommContractClient();
client.SendStr("hello");
client.SendStr("hello");
client.SendStr("hello");
client.Close();
}
}
}
运行程序:
Learning WCF:Life Cycle of Service instance的更多相关文章
- WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]
原文:WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇] 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来 ...
- Learning WCF Chapter1 Creating a New Service from Scratch
You’re about to be introduced to the WCF service. This lab isn’t your typical “Hello World”—it’s “He ...
- Learning WCF:Fault Handling
There are two types of Execptions which can be throwed from the WCF service. They are Application ex ...
- Learning WCF:A Simple Demo
This is a very simple demo which can help you create a wcf applition quickly. Create a Solution Open ...
- Learning WCF Chapter1 Hosting a Service in IIS
How messages reach a service endpoint is a matter of protocols and hosting. IIS can host services ov ...
- Learning WCF Chapter1 Generating a Service and Client Proxy
In the previous lab,you created a service and client from scratch without leveraging the tools avail ...
- Learning WCF Chapter1 Exposing Multiple Service Endpoints
So far in this chapter,I have shown you different ways to create services,how to expose a service en ...
- WCF 的 Service Instance模式和并发处理
WCF 的 Service Instance(实例)有三种模式 PerCall:每一次调用都创建一个实例,每一次调用结束后回收实例.此模式完全无状态. PerSession:调用者打开Channel时 ...
- WCF:为 SharePoint 2010 Business Connectivity Services 构建 WCF Web 服务(第 1 部分,共 4 部分)
转:http://msdn.microsoft.com/zh-cn/library/gg318615.aspx 摘要:通过此系列文章(共四部分)了解如何在 Microsoft SharePoint F ...
随机推荐
- model.form使用,配合form的钩子
一次model.form的使用记录,配合form钩子的过程 在写信息采集功能的时候,需要添加资产信息,使用modelform组件减少工作量 官网介绍:版本1.9.https://docs.django ...
- linux 的那些hung 检测机制
在dmesg中,看到如下信息: [:: seconds [:: seconds [:af: seconds [:af: seconds [:: seconds [:3b: seconds [:: se ...
- Linux安装配置JDK1.7
1 在/usr/local 文件夹下新建一个文件夹software ,将JDK放到此文件夹中 并在此文件夹下解压执行命令 tar zxvf jdk-8u144-linux-x64.tar. ...
- 使用jQuery+huandlebars遍历中if判断
兼容ie8(很实用,复制过来,仅供技术参考,更详细内容请看源地址:http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html) & ...
- VC6的工程转到VC2010或更高版本出现fatal error C1189编译错误的解决方法
以前也遇到过,当时解决了没写下来,这次正好又遇到了,就顺手写一下吧,别下次又忘记了. 当VC6的工程转到VC2010或更高版本时编译出现如下错误: c:\program files\microsoft ...
- python入门(四):字符串、编码、random
1.字符串 字符串基本有两种类型,str和bytes >>> s="a" >>> type(s) <class 'str'> ...
- window.innerWidth和document.body.clientWidth的区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java学习笔记(二):枚举值
枚举值的作用:枚举限制了变量要有一些预先定义的值,运用枚举值可以大大减少你的代码中的漏洞,举例来说,如果我们想为一家鲜榨果汁店编个程序,就可以将杯子的尺寸限制为小中和大.这样就可以确保人们不会定大中小 ...
- vue 自动识别PC、移动端,并跳转到对应页面
app.vuehead中添加 <!--自动识别PC.移动--> <script src="static/js/uaredirect.js" type=" ...
- kubernetes 基础
官网 kubernetes.io 有中文 中文网站 http://docs.kubernetes.org.cn kubectl 详细情况 https://kubernetes.io/docs/ref ...