Partilhar via


One-Way Serviços

O comportamento padrão de uma operação de serviço é o padrão solicitação-resposta. Em um padrão de solicitação-resposta, o cliente aguarda a mensagem de resposta, mesmo que a operação de serviço seja representada em código como um void método. Com uma operação unidirecional, apenas uma mensagem é transmitida. O destinatário não envia uma mensagem de resposta, nem o remetente espera uma.

Use o padrão de design unidirecional:

  • Quando o cliente precisa invocar operações e não é afetado pelo resultado da operação ao nível da operação.

  • Ao usar o NetMsmqBinding ou a MsmqIntegrationBinding classe. (Para obter mais informações sobre este cenário, consulte Filas no WCF.)

Quando uma operação é unidirecional, não há nenhuma mensagem de resposta para transportar informações de erro de volta para o cliente. Você pode detetar condições de erro utilizando funcionalidades do vínculo subjacente, como sessões fiáveis, ou projetando um contrato de serviço duplex que utiliza duas operações unidirecionais: um contrato do cliente para o serviço para realizar a operação de serviço e outro contrato do serviço para o cliente, permitindo ao serviço enviar falhas de volta ao cliente através de um callback que o cliente implementa.

Para criar um contrato de serviço unidirecional, defina o seu contrato de serviço, aplique a classe OperationContractAttribute para cada operação, e defina a propriedade IsOneWay para true, conforme demonstrado no código de exemplo a seguir.

[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 obter um exemplo completo, consulte o exemplo One-Way .

Bloqueio de clientes com operações One-Way

É importante perceber que, embora alguns aplicativos unidirecionais retornem assim que os dados de saída são gravados na conexão de rede, em vários cenários a implementação de uma associação ou de um serviço pode fazer com que um cliente WCF bloqueie o uso de operações unidirecionais. Em aplicativos cliente WCF, o objeto cliente WCF não retorna até que os dados de saída tenham sido gravados na conexão de rede. Isso é verdade para todos os padrões de troca de mensagens, incluindo operações unidirecionais; Isso significa que qualquer problema ao gravar os dados no transporte impede que o cliente retorne. Dependendo do problema, o resultado pode ser uma exceção ou um atraso no envio de mensagens para o serviço.

Por exemplo, se o transporte não conseguir encontrar o ponto de extremidade, uma System.ServiceModel.EndpointNotFoundException exceção será lançada sem muito atraso. No entanto, também é possível que o serviço não consiga ler os dados fora do fio por algum motivo, o que impede que a operação de envio de transporte do cliente retorne. Nesses casos, se o Binding.SendTimeout período na ligação de transporte do cliente for excedido, um System.TimeoutException é lançado, mas apenas depois de ultrapassado o tempo limite. Também é possível disparar tantas mensagens em um serviço que o serviço não pode processá-las depois de um determinado ponto. Nesse caso, também, o cliente unidirecional bloqueia até que o serviço possa processar as mensagens ou até que uma exceção seja lançada.

Outra variação é a situação na qual a propriedade service ServiceBehaviorAttribute.ConcurrencyMode é definida como Single e a vinculação usa sessões. Nesse caso, o dispatcher impõe a ordem nas mensagens recebidas (um requisito das sessões), o que impede que as mensagens subsequentes sejam lidas da rede até que o serviço tenha processado a mensagem anterior para aquela sessão. Novamente, o cliente bloqueia, mas se ocorre uma exceção depende se o serviço é capaz de processar os dados de espera antes das configurações de tempo limite no cliente.

Você pode atenuar parte desse problema inserindo um buffer entre o objeto cliente e a operação de envio do transporte do cliente. Por exemplo, usar chamadas assíncronas ou usar uma fila de mensagens na memória pode permitir que o objeto cliente retorne rapidamente. Ambas as abordagens podem aumentar a funcionalidade, mas o tamanho do pool de threads e da fila de mensagens ainda impõem limites.

É recomendado, em vez disso, que você examine os vários controles no serviço, bem como no cliente e, em seguida, teste os cenários do aplicativo para determinar a melhor configuração em ambos os lados. Por exemplo, se o uso de sessões estiver bloqueando o processamento de mensagens em seu serviço, você poderá definir a ServiceBehaviorAttribute.InstanceContextMode propriedade como PerCall para que cada mensagem possa ser processada por uma instância de serviço diferente e definir a ConcurrencyMode para Multiple permitir que mais de um thread envie mensagens de cada vez. Outra abordagem é aumentar as cotas de leitura das vinculações de serviço e cliente.

Ver também