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 ...
随机推荐
- Citrix XenApp登录服务器过程详解
详细流程: 1. 客户端上的receiver负责解析ICA文件,并根据ICA文件的内容发起连接请求.若是外网访问,则ICA文件中记录的是NetScaler的AG FQDN信息,连接请求发至NetSca ...
- 多线程利器-队列(queue)
#队列有3中模式,先进先出,先进后出,优先级 1:先进先出import queue q = queue.Queue() #默认是先进先出q.put(12)q.put('jack')q.put({'na ...
- python_08 函数式编程、高阶函数、map、filter、reduce函数、内置函数
函数式编程 编程方法论: 1.面向过程 找到解决问题的入口,按照一个固定的流程去模拟解决问题的流程 (1).搜索目标,用户输入(配偶要求),按照要求到数据结构内检索合适的任务 (2)表白,表白成功进入 ...
- Python常用内置函数介绍
Python提供了一个内联模块buildin.内联模块定义了一些开发中经常使用的函数,利用这些函数可以实现数据类型的转换.数据的计算.序列的处理等功能.下面将介绍内联模块中的常用函数. Python内 ...
- day41 mysql详细操作
复习 create table 表名( id int primary key auto_increment, 字段名 数据类型[(宽度) 约束] )engine=innodb charset=utf8 ...
- zabbix3.4 监控ESXI6.7
一.ESXI WEB界面 管理--高级配置启用 键 Config.HostAgent.plugins.solo.enableMob 访问:https://10.81.1.219/mob/?moid=h ...
- Linux磁盘配额
Step1:修改fstab文件,增加磁盘限额用户和用户组信息 # /etc/fstab# Created by anaconda on Sat Dec 29 04:48:18 2018## Acces ...
- 【网络编程】time_wait状态产生的原因,危害,如何避免
转自:https://blog.csdn.net/u013616945/article/details/77510925 做略微修改 仅供个人学习 1. time_wait状态如何产生? 在tcp ...
- Tomcat9报错 The valid characters are defined in RFC 7230 and RFC 3986
tomcat8项目移到tomcat9,出现如下问题 HTTP Status 400 – Bad Request Type Exception Report Message Invalid charac ...
- 写一份简单的webpack2 的配置文件,无比简单
这是一份自己用到的webpack2的配置写法,从看webpack2开始,发现自己越来越懒了,现在html文件都不想自己写了,直接自己生成... 哈哈,这次是可以无比完美的导入css啦 开发的时候在命令 ...