Serviços unidirecionais

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 deve chamar operações e não é afetado pelo resultado da operação no nível da operação.

  • Ao usar o NetMsmqBinding ou a MsmqIntegrationBinding classe. (Para obter mais informações sobre esse 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 usando recursos da associação subjacente, como sessões confiáveis, ou projetando um contrato de serviço duplex que usa duas operações unidirecionais — um contrato unidirecional do cliente para o serviço para chamar a operação de serviço e outro contrato unidirecional entre o serviço e o cliente para que o serviço possa enviar de volta falhas ao cliente usando um retorno de chamada que o cliente implementa.

Para criar um contrato de serviço unidirecional, defina seu contrato de serviço, aplique a OperationContractAttribute classe a cada operação e defina a IsOneWay propriedade como , conforme truemostrado 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 unidirecionais

É 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 vinculação de transporte do cliente for excedido, um System.TimeoutException será lançado, mas não até que o período de tempo limite tenha sido excedido. 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 de sessões), o que impede que as mensagens subsequentes sejam lidas fora da rede até que o serviço tenha processado a mensagem anterior para essa 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.

Consulte também