WCF服务实例的生命周期?

在创建WCF服务的过程中,我遇到了一个对我来说不熟悉的术语。 基本上在指定InstanceContextMode我有几个选项,包括; PerSessionPerSessionSingle 。 这是我正在学习的示例中的代码:

 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class EvalService : IEvalService { ... 

现在,他说这样做只会在运行时创建一个服务实例。 这是什么意思? 我认为,每次与Web服务建立连接时,它都被视为一个单独的实例。

对于每个请求,它是否仍然存在,这是我的服务实例? 根据文档中提到的其他成员来判断,假设这是它的工作方式是否安全?

根据文档:

只有一个InstanceContext对象用于所有传入呼叫,并且在呼叫之后不会被回收。 如果服务对象不存在,则创建一个服务对象。

所以只有一个实例,并且在调用之后它没有被清理掉。 这就像您的WCF服务的Singleton。 因此,您需要注意共享内存和资源。

回答你的问题 – 是的,这是它的工作方式。

更新添加示例:我从MSDN修改了一些示例以显示InstanceContextMode.Single的效果。 即使我使用两个不同的客户端,您也会看到操作计数将继续增加。 如果我将InstanceContextMode更改为PerCall ,则计数将不同(它将为零)。

自托管服务:

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class CalculatorService : ICalculatorInstance { static Object syncObject = new object(); static int instanceCount; int instanceId; int operationCount; public CalculatorService() { lock (syncObject) { instanceCount++; instanceId = instanceCount; } } public double Add(double n1, double n2) { operationCount++; return n1 + n2; } public double Subtract(double n1, double n2) { Interlocked.Increment(ref operationCount); return n1 - n2; } public double Multiply(double n1, double n2) { Interlocked.Increment(ref operationCount); return n1 * n2; } public double Divide(double n1, double n2) { Interlocked.Increment(ref operationCount); return n1 / n2; } public string GetInstanceContextMode() { // Return the InstanceContextMode of the service ServiceHost host = (ServiceHost)OperationContext.Current.Host; ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find(); return behavior.InstanceContextMode.ToString(); } public int GetInstanceId() { // Return the id for this instance return instanceId; } public int GetOperationCount() { // Return the number of ICalculator operations performed // on this instance lock (syncObject) { return operationCount; } } } public class Program { static void Main(string[] args) { Uri baseAddress = new Uri("http://localhost:12345/calc"); using (ServiceHost host = new ServiceHost(typeof(CalculatorService), baseAddress)) { // Enable metadata publishing. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; host.Description.Behaviors.Add(smb); // Open the ServiceHost to start listening for messages. Since // no endpoints are explicitly configured, the runtime will create // one endpoint per base address for each service contract implemented // by the service. host.Open(); Console.WriteLine("The service is ready at {0}", baseAddress); Console.WriteLine("Press  to stop the service."); Console.ReadLine(); // Close the ServiceHost. host.Close(); } Console.WriteLine(); Console.WriteLine("Press  to terminate client."); Console.ReadLine(); } } 

客户:

 class Program { static void Main() { // Create a client. CalculatorInstanceClient client = new CalculatorInstanceClient(); string instanceMode = client.GetInstanceContextMode(); Console.WriteLine("InstanceContextMode: {0}", instanceMode); Console.WriteLine("client1's turn"); Console.WriteLine("2 + 2 = {0}", client.Add(2, 2).ToString()); Console.WriteLine("3 - 1 = {0}", client.Subtract(3, 1).ToString()); Console.WriteLine("number of operations = {0}", client.GetOperationCount().ToString()); // Create a second client. CalculatorInstanceClient client2 = new CalculatorInstanceClient(); Console.WriteLine("client2's turn"); Console.WriteLine("2 + 2 = {0}", client2.Add(2, 2).ToString()); Console.WriteLine("3 - 1 = {0}", client2.Subtract(3, 1).ToString()); Console.WriteLine("number of operations = {0}", client2.GetOperationCount().ToString()); Console.WriteLine(); Console.WriteLine("Press  to terminate client."); Console.ReadLine(); } } 

InstanceContextMode.Single对应于单例服务,即服务实例服务器端对于所有传入请求都是相同的。

一些评论:

  • 您的服务可能会被主机终止,即使它是一个单独的服务器,如果您的服务是在iis中托管的话可能就是这种情况
  • 它是实例上下文,它是一个可能与实际服务实例分离的单例(但现在让它保持简单……)
  • 如果在单例服务中未正确捕获exception,则可能会阻止任何后续请求成功

这意味着WCF只创建了一个类的实例。 所有请求都由该实例处理。 包括multithreading和并发问题。

虽然它可能是一个实现细节,但我怀疑你的类是persistet(它必须是可序列化的,这不是一个要求)。 只要需要(即关联的ServiceHost是打开的),一个实例就会存在。

是的,共享服务实例意味着服务器只创建了一个实例,在请求之间共享。

特别是,在创建实例时,将调用服务对象的构造函数一次。 这可能很重要,例如,如果您使用某种forms的身份validation来模拟上下文的身份(共享实例可能需要一些额外的工作来处理这种情况)。