在创建WCF服务的过程中,我遇到了一个对我来说很新的术语。基本上在指定InstanceContextMode
时我有几个选项,包括; PerSession
,PerCall
和Single
。这是我正在学习的样本中的代码:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class EvalService : IEvalService { ...
现在,他说这样做只会在运行时创建一个服务实例。这是什么意思?我认为每次与Web服务建立连接时都会将其视为单独的实例。
对于每个请求,它是否仍然存在,这是我的服务实例?根据{{3}}中提到的其他成员来判断,假设这是它的工作方式是否安全?
答案 0 :(得分:11)
根据文档:
只有一个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<ServiceBehaviorAttribute>();
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 <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
Console.WriteLine();
Console.WriteLine("Press <ENTER> 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 <ENTER> to terminate client.");
Console.ReadLine();
}
}
答案 1 :(得分:0)
这意味着WCF只创建了一个类的实例。所有请求都由该实例处理。包括多线程和并发问题。
虽然它可能是一个实现细节,但我怀疑你的类是persistet(它必须是可序列化的,这不是一个要求)。只要需要(即关联的ServiceHost
打开),一个实例就会存在。
答案 2 :(得分:0)
是的,共享服务实例意味着服务器只创建了一个实例,在请求之间共享。
特别是,在创建实例时,将调用服务对象的构造函数一次。这可能很重要,例如,如果您使用某种形式的身份验证来模拟上下文的身份(共享实例可能需要一些额外的工作来处理这种情况)。