Compartir por


One-Way Servicios

El comportamiento predeterminado de una operación de servicio es el patrón de solicitud-respuesta. En un patrón de solicitud-respuesta, el cliente espera el mensaje de respuesta, incluso si la operación del servicio se representa en el código como método void . Con una operación unidireccional, solo se transmite un mensaje. El receptor no envía un mensaje de respuesta ni el remitente espera uno.

Use el patrón de diseño unidireccional:

  • Cuando el cliente debe llamar a las operaciones y no está afectado por el resultado de la operación en el nivel de la operación.

  • Cuando se usa la NetMsmqBinding o la MsmqIntegrationBinding clase. (para obtener más información sobre este escenario, consulte Colas en WCF).

Cuando una operación es unidireccional, no hay ningún mensaje de respuesta para devolver información de error al cliente. Puede detectar las condiciones de error mediante las características del enlace subyacente, como sesiones de confianza, o diseñando un contrato de servicio dúplex que utiliza dos operaciones unidireccionales; es decir, un contrato unidireccional del cliente al servicio para llamar a la operación de servicio y otro contrato unidireccional entre el servicio y el cliente para que el servicio pueda devolver los errores al cliente utilizando una devolución de llamada que el cliente implementa.

Para crear un contrato de servicio unidireccional, defina el contrato de servicio, aplique la clase OperationContractAttribute a cada operación y establezca la propiedad IsOneWay en true, como se muestra en el código de ejemplo siguiente.

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

Para obtener un ejemplo completo, consulte el ejemplo unidireccional .

Clientes que se bloquean con operaciones unidireccionales

Es importante tener en cuenta que, aunque algunas aplicaciones unidireccionales devuelven tan pronto como los datos salientes se escriben en la conexión de red, en varios escenarios la implementación de un enlace o de un servicio puede hacer que un cliente WCF bloquee el uso de operaciones unidireccionales. En las aplicaciones cliente WCF, el objeto de cliente WCF no se devuelve hasta que los datos salientes se hayan escrito en la conexión de red. Esto es cierto para todos los patrones de intercambio de mensajes, incluidas las operaciones unidireccionales; esto significa que cualquier problema al escribir los datos en el transporte impide que el cliente devuelva. Dependiendo del problema, el resultado podría ser una excepción o un retraso en el envío de mensajes al servicio.

Por ejemplo, si el transporte no puede encontrar el punto de conexión, se lanza una excepción System.ServiceModel.EndpointNotFoundException casi de inmediato. Sin embargo, también es posible que el servicio no pueda leer los datos fuera de la conexión por alguna razón, lo que evita que se devuelva la operación de envío de transporte del cliente. En estos casos, si se supera el período Binding.SendTimeout en el enlace de transporte de cliente, se emitirá System.TimeoutException, pero no hasta que se haya superado el período de tiempo de espera. También es posible disparar tantos mensajes a un servicio que el servicio no pueda procesarlos más allá de un cierto punto. En este caso, también, el cliente unidireccional se bloquea hasta que el servicio pueda procesar los mensajes o hasta que se produzca una excepción.

Otra variación es la situación en la que la propiedad de servicio ServiceBehaviorAttribute.ConcurrencyMode se establece en Single y el enlace utiliza sesiones. En este caso, el distribuidor exige la clasificación en los mensajes entrantes (un requisito de sesiones), que evita que los mensajes subsiguientes se lean fuera de la red hasta que el servicio haya procesado el mensaje anterior para esa sesión. De nuevo, el cliente se bloquea, pero si una excepción se produce depende de si el servicio puede procesar los datos de espera antes de la configuración del tiempo de espera en el cliente.

Puede mitigar algunos de estos problemas insertando un búfer entre el objeto de cliente y la operación de envío de transporte del cliente. Por ejemplo, el uso de llamadas asincrónicas o de una cola de mensajes en memoria puede permitir que el objeto cliente responda rápidamente. Ambos enfoques pueden aumentar la funcionalidad, pero el tamaño del grupo de subprocesos y la cola de mensajes siguen aplicando límites.

Se recomienda, en su lugar, examinar los distintos controles en el servicio, así como en el cliente, y luego probar los escenarios de la aplicación para determinar la mejor configuración en cualquiera de los lados. Por ejemplo, si el uso de sesiones está bloqueando el procesamiento de mensajes en su servicio, puede configurar la propiedad ServiceBehaviorAttribute.InstanceContextMode a PerCall para que cada mensaje pueda ser procesado por una instancia diferente del servicio, y configurar ConcurrencyMode a Multiple para permitir que más de un subproceso envíe mensajes simultáneamente. Otro enfoque es aumentar las cuotas de lectura de los enlaces de cliente y servicio.

Consulte también