Поделиться через


службы One-Way

Поведение службы по умолчанию — это шаблон ответа на запрос. В шаблоне ответа на запрос клиент ожидает ответа, даже если операция службы представлена в коде void как метод. При односторонней операции передается только одно сообщение. Получатель не отправляет ответное сообщение и не ожидает его.

Используйте односторонний шаблон проектирования.

  • Когда клиент должен вызывать операции, но результат этих действий на уровне операций на него не влияет.

  • При использовании NetMsmqBinding класса или MsmqIntegrationBinding класса. (Дополнительные сведения об этом сценарии см. в разделе "Очереди" в WCF.)

При односторонним выполнении операции нет сообщения ответа для передачи сведений об ошибке обратно клиенту. Вы можете обнаружить условия ошибки с помощью функций базовой привязки, таких как надежные сеансы, или путем разработки дуплексного контракта службы, использующего две односторонние операции — односторонний контракт от клиента к службе для вызова операции службы и другой односторонний контракт между службой и клиентом, чтобы служба могла возвращать ошибки клиенту с помощью обратного вызова, который реализует клиент.

Чтобы создать односторонний контракт службы, определите контракт службы, примените OperationContractAttribute класс к каждой операции и задайте IsOneWay для свойства значение true, как показано в следующем примере кода.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]  
public interface IOneWayCalculator  
{  
    [OperationContract(IsOneWay=true)]  
    void Add(double n1, double n2);  
    [OperationContract(IsOneWay = true)]  
    void Subtract(double n1, double n2);  
    [OperationContract(IsOneWay = true)]  
    void Multiply(double n1, double n2);  
    [OperationContract(IsOneWay = true)]  
    void Divide(double n1, double n2);  
}  

Полный пример см. в примере one-Way .

Блокировка клиентов с помощью операций One-Way

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

Например, если транспорт не может найти конечную System.ServiceModel.EndpointNotFoundException точку, создается исключение без большой задержки. Однако также возможно, что служба не может считывать данные от провода по какой-то причине, что предотвращает возврат операции отправки транспорта клиента. В таких случаях, если Binding.SendTimeout период привязки транспорта клиента превышен, создается исключение System.TimeoutException, но только после превышения периода ожидания. Кроме того, можно отправить службе столько сообщений, что она не сможет обработать их после определенного предела. В этом случае клиент блокируется в одностороннем режиме до тех пор, пока служба не сможет обработать сообщения или пока не возникнет исключение.

Другим вариантом является ситуация, в которой для свойства службы ServiceBehaviorAttribute.ConcurrencyMode задано значение Single , и привязка использует сеансы. В этом случае диспетчер принудительно упорядочивает входящие сообщения (требование сеансов), что предотвращает считывание последующих сообщений из сети до тех пор, пока служба не обработала предыдущее сообщение для этого сеанса. Опять клиент блокируется, но возникновение исключения зависит от того, сможет ли служба обработать ожидающие данные до истечения времени ожидания, установленного на клиенте.

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

Вместо этого рекомендуется проверить различные элементы управления в службе, а также на клиенте, а затем протестировать сценарии приложения, чтобы определить оптимальную конфигурацию на обеих сторонах. Если использование сеанса блокирует обработку сообщений в вашей службе, можно задать свойство ServiceBehaviorAttribute.InstanceContextModePerCall, чтобы каждое сообщение обрабатывалось другим экземпляром службы, и установить значение ConcurrencyModeMultiple, чтобы разрешить нескольким потокам распределять сообщения одновременно. Другой подход заключается в увеличении квот на чтение привязок службы и клиента.

См. также