Partilhar via


Reentrante ConcurrencyMode

O exemplo de Reentrante demonstra a necessidade e as implicações do uso de ConcurrencyMode.Reentrant em uma implementação de serviço. ConcurrencyMode.Reentrant implica que o serviço (ou retorno de chamada) processa apenas uma mensagem em um determinado momento (análogo a ConcurencyMode.Single). Para garantir a segurança do thread, o Windows Communication Foundation (WCF) bloqueia o InstanceContext processamento de uma mensagem para que nenhuma outra mensagem possa ser processada. No caso do modo Reentrante, o InstanceContext é desbloqueado imediatamente antes de o serviço fazer uma chamada de saída, permitindo assim que a chamada subsequente (que pode ser reentrante, conforme demonstrado na amostra) obtenha o bloqueio na próxima vez que entrar no serviço. Para demonstrar o comportamento, o exemplo mostra como um cliente e um serviço podem enviar mensagens entre si usando um contrato duplex.

O contrato definido é um contrato duplex com o Ping método sendo implementado pelo serviço e o método Pong de retorno de chamada sendo implementado pelo cliente. Um cliente invoca o método do Ping servidor com uma contagem de ticks, iniciando assim a chamada. O serviço verifica se a contagem de ticks não é igual a 0 e, em seguida, invoca o método callbacks Pong enquanto diminui a contagem de ticks. Isso é feito pelo código a seguir no exemplo.

public void Ping(int ticks)
{
     Console.WriteLine("Ping: Ticks = " + ticks);
     //Keep pinging back and forth till Ticks reaches 0.
     if (ticks != 0)
     {
         OperationContext.Current.GetCallbackChannel<IPingPongCallback>().Pong((ticks - 1));
     }
}

A implementação do retorno de Pong chamada tem a mesma lógica da Ping implementação. Ou seja, ele verifica se a contagem de ticks não é zero e, em seguida, invoca o Ping método no canal de retorno de chamada (neste caso, é o canal que foi usado para enviar a mensagem original Ping ) com a contagem de tick diminuída por 1. No momento em que a contagem de ticks atinge 0, o método retorna desembrulhando todas as respostas de volta para a primeira chamada feita pelo cliente que iniciou a chamada. Isso é mostrado na implementação de retorno de chamada.

public void Pong(int ticks)
{
    Console.WriteLine("Pong: Ticks = " + ticks);
    if (ticks != 0)
    {
        //Retrieve the Callback  Channel (in this case the Channel which was used to send the
        //original message) and make an outgoing call until ticks reaches 0.
        IPingPong channel = OperationContext.Current.GetCallbackChannel<IPingPong>();
        channel.Ping((ticks - 1));
    }
}

Ambos os métodos e Pong são solicitação/resposta, o Ping que significa que a primeira chamada para Ping não retorna até que a chamada para CallbackChannel<T>.Pong() retorne. No cliente, o Pong método não pode retornar até que a próxima Ping chamada que ele fez retorna. Como o retorno de chamada e o serviço devem fazer chamadas de solicitação/resposta de saída antes de poderem responder à solicitação pendente, ambas as implementações devem ser marcadas com o comportamento ConcurrencyMode.Reentrant.

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.

Demonstra

Para executar o exemplo, crie os projetos cliente e servidor. Em seguida, abra duas janelas de comando e altere os diretórios para os <diretórios sample>\CS\Service\bin\debug e <sample>\CS\Client\bin\debug. Em seguida, inicie o serviço digitando service.exe e, em seguida, invoque o Client.exe com o valor inicial de ticks passados como um argumento de entrada. Uma saída de amostra para 10 ticks é mostrada.

Prompt>Service.exe
ServiceHost Started. Press Enter to terminate service.
Ping: Ticks = 10
Ping: Ticks = 8
Ping: Ticks = 6
Ping: Ticks = 4
Ping: Ticks = 2
Ping: Ticks = 0

Prompt>Client.exe 10
Pong: Ticks = 9
Pong: Ticks = 7
Pong: Ticks = 5
Pong: Ticks = 3
Pong: Ticks = 1