Compartilhar via


Unidirecional

O exemplo de operação unidirecional demonstra um contato de serviço com operações de serviço unidirecionais. O cliente não aguarda a conclusão das operações de serviço, como ocorre com as operações de serviço bidirecionais. Este exemplo é baseado na Introdução e usa a associação wsHttpBinding. O serviço deste exemplo é um aplicativo de console auto-hospedado que permite que você observe o serviço que recebe e processa as solicitações. O cliente também é um aplicativo de console.

Observação

O procedimento de instalação e as instruções de build desse exemplo estão no final deste tópico.

Para criar um contrato de serviço unidirecional, defina o contrato de serviço, aplique a classe OperationContractAttribute a cada operação e defina IsOneWay como true, conforme mostrado no seguinte código de exemplo:

[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 demonstrar que o cliente não aguarda a conclusão das operações de serviço, o código de serviço deste exemplo implementa um atraso de cinco segundos, conforme mostrado no seguinte código de exemplo:

// This service class implements the service contract.
// This code writes output to the console window.
 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
    InstanceContextMode = InstanceContextMode.PerCall)]
public class CalculatorService : IOneWayCalculator
{
    public void Add(double n1, double n2)
    {
        Console.WriteLine("Received Add({0},{1}) - sleeping", n1, n2);
        System.Threading.Thread.Sleep(1000 * 5);
        double result = n1 + n2;
        Console.WriteLine("Processing Add({0},{1}) - result: {2}", n1, n2, result);
    }
    ...
}

Quando o cliente chama o serviço, a chamada é retornada sem aguardar a conclusão da operação de serviço.

Quando você executa o exemplo, as atividades de cliente e de serviço são exibidas nas janelas do serviço e do console do cliente. Você pode ver o serviço receber mensagens do cliente. Pressione ENTER em cada janela do console para desligar o serviço e o cliente.

O cliente é concluído antes do serviço, demonstrando que um cliente não aguarda a conclusão das operações de serviço unidirecionais. A saída do cliente é a seguinte:

Add(100,15.99)
Subtract(145,76.54)
Multiply(9,81.25)
Divide(22,7)

Press <ENTER> to terminate client.

A seguinte saída de serviço é mostrada:

The service is ready.
Press <ENTER> to terminate service.

Received Add(100,15.99) - sleeping
Received Subtract(145,76.54) - sleeping
Received Multiply(9,81.25) - sleeping
Received Divide(22,7) - sleeping
Processing Add(100,15.99) - result: 115.99
Processing Subtract(145,76.54) - result: 68.46
Processing Multiply(9,81.25) - result: 731.25
Processing Divide(22,7) - result: 3.14285714285714

Observação

O HTTP é, por definição, um protocolo de solicitação/resposta. Quando uma solicitação é feita, uma resposta é retornada. Isso é verdadeiro até mesmo para uma operação de serviço unidirecional exposta por HTTP. Quando a operação é chamada, o serviço retorna um código de status HTTP igual a 202 antes da execução da operação de serviço. Esse código de status significa que a solicitação foi aceita para processamento. No entanto, o processamento não foi concluído. O cliente que chamou a operação faz o bloqueio até receber a resposta 202 do serviço. Isso pode causar algum comportamento inesperado quando várias mensagens unidirecionais são enviadas por meio de uma associação configurada para usar sessões. A associação wsHttpBinding usada neste exemplo é configurada para usar sessões por padrão a fim de estabelecer um contexto de segurança. Por padrão, as mensagens de uma sessão têm a garantia de chegar na ordem em que são enviadas. Por isso, quando a segunda mensagem de uma sessão é enviada, ela não é processada até que a primeira mensagem seja processada. O resultado disso é que o cliente não recebe a resposta 202 de uma mensagem até que o processamento da mensagem anterior tenha sido concluído. Portanto, o cliente parece bloquear cada chamada de operação seguinte. Para evitar esse comportamento, este exemplo configura o runtime para enviar mensagens simultaneamente para instâncias distintas para processamento. O exemplo define InstanceContextMode como PerCall para que cada mensagem possa ser processada por uma instância diferente. ConcurrencyMode é definido como Multiple para permitir que mais de um thread envie mensagens por vez.

Para configurar, compilar, e executar o exemplo

  1. Verifique se você executou o Procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Para compilar a edição .NET do C# ou do Visual Basic da solução, siga as instruções contidas em Como Compilar as Amostras do Windows Communication Foundation.

  3. Para executar o exemplo em uma configuração de computador único ou cruzado, siga as instruções em Como executar os exemplos do Windows Communication Foundation.

Observação

Execute o serviço antes de executar o cliente e desligue o cliente antes de desligar o serviço. Isso evita uma exceção de cliente quando o cliente não pode fechar a sessão de segurança de maneira limpa porque o serviço foi removido.