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
Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.
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.
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