Só de ida

O exemplo Oneway demonstra um contato de serviço com operações de serviço unidirecional. O cliente não espera que as operações de serviço sejam concluídas, como é o caso das operações de serviço bidirecional. Este exemplo é baseado em Introdução e usa a wsHttpBinding associação. O serviço neste exemplo é um aplicativo de console auto-hospedado para permitir que você observe o serviço que recebe e processa solicitações. O cliente também é um aplicativo de console.

Nota

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

Para criar um contrato de serviço unidirecional, defina seu contrato de serviço, aplique a OperationContractAttribute classe a cada operação e defina IsOneWay como true mostrado 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 demonstrar que o cliente não espera que as operações de serviço sejam concluídas, o código de serviço neste exemplo implementa um atraso de cinco segundos, conforme mostrado no código de exemplo a seguir:

// 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 retorna sem esperar que a operação de serviço seja concluída.

Quando você executa o exemplo, as atividades do cliente e do serviço são exibidas nas janelas do console do serviço e 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 termina à frente do serviço, demonstrando que um cliente não espera que as operações de serviço unidirecionais sejam concluídas. 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

Nota

HTTP é, por definição, um protocolo de solicitação/resposta; Quando uma solicitação é feita, uma resposta é retornada. Isso é verdade 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 de 202 antes que a operação de serviço tenha sido executada. Esse código de status significa que a solicitação foi aceita para processamento, mas o processamento ainda não foi concluído. O cliente que chamou a operação bloqueia até receber a resposta 202 do serviço. Isso pode causar algum comportamento inesperado quando várias mensagens unidirecionais são enviadas usando uma associação configurada para usar sessões. A wsHttpBinding associação usada neste exemplo é configurada para usar sessões por padrão para estabelecer um contexto de segurança. Por padrão, as mensagens em 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 tenha sido 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. O cliente, portanto, parece bloquear em cada chamada de operação subsequente. Para evitar esse comportamento, este exemplo configura o tempo de execução para enviar mensagens simultaneamente para instâncias distintas para processamento. O exemplo define InstanceContextMode para PerCall que cada mensagem possa ser processada por uma instância diferente. ConcurrencyMode está definido para Multiple permitir que mais de um thread envie mensagens de cada vez.

Para configurar, compilar e executar o exemplo

  1. Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Para criar a edição C# ou Visual Basic .NET da solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

  3. Para executar o exemplo em uma configuração de máquina única ou cruzada, siga as instruções em Executando os exemplos do Windows Communication Foundation.

Nota

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 corretamente porque o serviço desapareceu.