Односторонние службыOne-Way Services

По умолчанию операция службы выполняется по шаблону "запрос-ответ".The default behavior of a service operation is the request-reply pattern. В соответствии с шаблоном "запрос-ответ" клиент ждет ответного сообщения, даже если операция службы представлена в коде в виде метода void.In a request-reply pattern, the client waits for the reply message, even if the service operation is represented in code as a void method. В случае односторонних операций передается только одно сообщение.With a one-way operation, only one message is transmitted. Получатель не отправляет ответное сообщение, а отправитель не ожидает получения этого сообщения.The receiver does not send a reply message, nor does the sender expect one.

Односторонний шаблон используется в следующих случаях.Use the one-way design pattern:

  • Если клиент должен вызывать операции и не зависит от результата выполнения этих операций на уровне операций.When the client must call operations and is not affected by the result of the operation at the operation level.

  • При использовании класса NetMsmqBinding или MsmqIntegrationBinding.When using the NetMsmqBinding or the MsmqIntegrationBinding class. (Дополнительные сведения об этом сценарии см. в разделе очереди в WCF.)(For more information about this scenario, see Queues in WCF.)

Если операция является односторонней, ответное сообщение, в котором могут передаваться сведения об ошибке, клиенту не отправляется.When an operation is one-way, there is no response message to carry error information back to the client. Условия возникновения ошибок можно определять с помощью возможностей соответствующей привязки, например надежных сеансов, или посредством разработки дуплексного контракта службы, который использует две односторонних операции - односторонний контракт от клиента к службе для вызова операции службы и еще один односторонний контракт между службой и клиентом, чтобы служба могла вернуть клиенту ошибки, используя реализуемый в клиенте обратный вызов.You can detect error conditions by using features of the underlying binding, such as reliable sessions, or by designing a duplex service contract that uses two one-way operations—a one-way contract from the client to the service to call service operation and another one-way contract between the service and the client so that the service can send back faults to the client using a callback that the client implements.

Чтобы создать односторонний контракт службы, определите контракт службы, примените класс OperationContractAttribute к каждой из операций, и установите свойство IsOneWay равным true, как показано в следующем примере кода.To create a one-way service contract, define your service contract, apply the OperationContractAttribute class to each operation, and set the IsOneWay property to true, as shown in the following sample code.

[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);  
}  

Полный пример см. в разделе односторонний пример.For a complete example, see the One-Way sample.

Блокировка клиентов с помощью односторонних операцийClients Blocking with One-Way Operations

Важно понимать, что хотя некоторые односторонние приложения возвращают, как только исходящие данные записываются в сетевое подключение, в нескольких сценариях реализация привязки или службы может привести к блокировке клиента WCF с помощью односторонних операций.It is important to realize that while some one-way applications return as soon as the outbound data is written to the network connection, in several scenarios the implementation of a binding or of a service can cause a WCF client to block using one-way operations. В клиентских приложениях WCF объект клиента WCF не возвращает значение, пока исходящие данные не будут записаны в сетевое подключение.In WCF client applications, the WCF client object does not return until the outbound data has been written to the network connection. Это относится ко всем шаблонам обмена сообщениями, включая односторонние операции; это означает, что любая проблема, связанная с передачей данных через транспортный канал, не позволит клиенту вернуть управление.This is true for all message exchange patterns, including one-way operations; this means that any problem writing the data to the transport prevents the client from returning. В зависимости от проблемы ее результатом может быть исключение или задержка при отправке сообщения службе.Depending upon the problem, the result could be an exception or a delay in sending messages to the service.

Например, если транспорту не удается найти конечную точку, исключение System.ServiceModel.EndpointNotFoundException будет создано без большой задержки.For example, if the transport cannot find the endpoint, a System.ServiceModel.EndpointNotFoundException exception is thrown without much delay. Однако также возможна ситуация, при которой службе по какой-либо причине не удается считать данные из сети, в результате чего операция отправки на стороне клиента не может быть завешена.However, it is also possible that the service is unable to read the data off the wire for some reason, which prevents the client transport send operation from returning. В этих случаях, если превышается время Binding.SendTimeout привязки транспорта клиента, создается исключение System.TimeoutException - но не раньше истечения времени ожидания.In these cases, if the Binding.SendTimeout period on the client transport binding is exceeded, a System.TimeoutException is thrown—but not until the timeout period has been exceeded. Кроме того, службе может быть отправлено так много сообщений, что в какой-то момент служба больше не сможет их обрабатывать.It is also possible to fire so many messages at a service that the service cannot process them past a certain point. В этом случае односторонний клиент также блокируется, пока служба не сможет обработать сообщения или пока не будет создано исключение.In this case, too, the one-way client blocks until the service can process the messages or until an exception is thrown.

Подобная блокировка также может происходить в том случае, если свойство ServiceBehaviorAttribute.ConcurrencyMode службы имеет значение Single, а привязка использует сеансы.Another variation is the situation in which the service ServiceBehaviorAttribute.ConcurrencyMode property is set to Single and the binding uses sessions. В этом случае диспетчер принудительно упорядочивает входящие сообщения (требование сеансов), что не допускает чтения из сети следующего сообщения, пока служба не обработала предыдущее сообщение для этого сеанса.In this case, the dispatcher enforces ordering on the incoming messages (a requirement of sessions), which prevents subsequent messages from being read off the network until the service has processed the preceding message for that session. Клиент в этом случае также блокируется, но появление исключения зависит от того, успеет ли служба обработать ожидающие данные, пока не истечет установленное на стороне клиента время ожидания.Again, the client blocks, but whether an exception occurs depends upon whether the service is able to process the waiting data prior to the timeout settings on the client.

Можно частично ограничить эту проблему, поместив буфер между объектом клиента и операцией отправки транспорта клиента.You can mitigate some of this problem by inserting a buffer between the client object and the client transport's send operation. Например, при использовании асинхронных вызовов или очереди сообщений в памяти объект клиента может быстро возвращать управление.For example, using asynchronous calls or using an in-memory message queue can enable the client object to return quickly. Оба подхода могут расширить функциональность, но размер пула потоков и очереди сообщений по-прежнему накладывает ограничения.Both approaches may increase functionality, but the size of the thread pool and the message queue still enforce limits.

Вместо этого рекомендуется изучить различные элементы управления службы и клиента и испытать различные сценарии работы приложения, чтобы определить наилучшую конфигурацию на каждой из сторон.It is recommended, instead, that you examine the various controls on the service as well as on the client, and then test your application scenarios to determine the best configuration on either side. Например, если использование сеансов блокирует обработку сообщений на стороне службы, можно установить для свойства ServiceBehaviorAttribute.InstanceContextMode значение PerCall, чтобы каждое сообщение обрабатывалось отдельным экземпляром службы, а также установить свойство ConcurrencyMode равным Multiple, чтобы одновременно распределять сообщения могло более одного потока.For example, if the use of sessions is blocking the processing of messages on your service, you can set the ServiceBehaviorAttribute.InstanceContextMode property to PerCall so that each message can be processed by a different service instance, and set the ConcurrencyMode to Multiple in order to allow more than one thread to dispatch messages at a time. Еще одно возможное решение - увеличить квоты чтения привязок службы и клиента.Another approach is to increase the read quotas of the service and client bindings.

См. такжеSee also