Срок службы экземпляра службы WCF?

в процессе создания службы WCF я столкнулся с новым для меня термином. В основном при указании InstanceContextMode меня есть несколько вариантов, в том числе; PerSession , PerCall и Single . Вот код из образца, который я изучаю:

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

Теперь он заявил, сделав это, что во время выполнения будет создан только один экземпляр моего сервиса. Что это значит? Я думал, что каждый раз при подключении к веб-сервису он обрабатывается как отдельный экземпляр.

Сохраняется ли это, этот экземпляр моего сервиса, для каждого сделанного запроса? Судя по другим членам, упомянутым в документах , можно ли предположить, что так оно и работает?

В документах:

Только один объект InstanceContext используется для всех входящих вызовов и не перерабатывается после вызовов. Если объект службы не существует, он создается.

Таким образом, есть только один экземпляр, и он не очищается после вызова. Это похоже на Singleton для вашей службы WCF. Поэтому вам нужно быть осторожным в отношении общей памяти и ресурсов.

Чтобы ответить на ваш вопрос – да, так оно и работает.

UPDATE Добавленный образец: я изменил несколько образцов из 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(); } } - [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
  • Это контекст экземпляра, который является одноэлементным, который может быть отделен от фактических экземпляров службы (но давайте сделаем это простым на данный момент …)
  • Если исключение не попало должным образом в однопользовательскую службу, это может помешать дальнейшему последующему запросу

Это означает, что WCF создает только один экземпляр вашего classа. Все запросы обрабатываются этим экземпляром. Включены проблемы многопоточности и параллелизма.

Хотя это, вероятно, будет деталью реализации, я сомневаюсь, что ваш class persistet (для этого он должен быть сериализуемым, что не является обязательным требованием). Один экземпляр просто существует до тех пор, пока он необходим (т. ServiceHost Связанный с ним ServiceHost открыт).

Да, совместное использование экземпляра службы означает, что существует только один экземпляр, созданный сервером, совместно используемый между запросами.

В частности, конструктор объекта службы будет вызываться один раз, когда экземпляр будет создан. Это может быть важно, например, если вы используете какую-либо форму аутентификации, олицетворяя идентичность контекста (для общих экземпляров потенциально может потребоваться дополнительная работа для обработки такого случая).