ConcurrencyMode reentrante
El ejemplo de reentrante muestra la necesidad y las implicaciones de usar ConcurrencyMode.Reentrant en una implementación del servicio. ConcurrencyMode.Reentrant implica que el servicio (o la devolución de llamada) procesa solo uno mensaje en una hora determinada (análogo a ConcurencyMode.Single
). Para garantizar la seguridad para subprocesos, Windows Communication Foundation (WCF) bloquea el procesamiento de un mensaje InstanceContext
para que no se puedan procesar otros mensajes. En el caso del modo reentrante, InstanceContext
se desbloquea justo antes de que el servicio haga una llamada de salida por la que permite la llamada subsiguiente, (que puede ser reentrante como se muestra en el ejemplo) para obtener el bloqueo la próxima vez que entre al servicio. Para mostrar el comportamiento, el ejemplo muestra cómo un cliente y el servicio pueden enviar los mensajes entre sí utilizando un contrato dúplex.
El contrato definido es un contrato dúplex con el método Ping
siendo implementado por el servicio y el método de devolución de llamadaPong
siendo implementado por el cliente. Un cliente invoca el método del servidor Ping
con un recuento del paso que inicia así la llamada. El servicio comprueba si el recuento del paso no es igual a 0 y a continuación, invoca las devoluciones de llamada el método Pong
disminuyendo el recuento del paso. El código siguiente realiza esta operación en el ejemplo.
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));
}
}
La implementación Pong
de la devolución de llamada tiene la misma lógica que la implementación Ping
. Es decir, comprueba si el contador no es cero y, a continuación, invoca el método Ping
en el canal de devolución de llamada (en este caso, es el canal que fue utilizado para enviar el mensaje Ping
original) con el contador disminuido en 1. El momento en que el contador llegue a 0, el método vuelve y desempaqueta de nuevo todas las respuestas a la primera llamada realizada por el cliente que inició la llamada. Esto se muestra en la implementación de devolución de llamada.
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));
}
}
Ping
y los métodos Pong
son solicitud/respuesta, lo cual significa que la primera llamada a Ping
no vuelve hasta que la llamada CallbackChannel<T>.Pong()
se devuelve. En el cliente, el método Pong
no puede devolverse hasta que la siguiente llamada Ping
que se realizó se devuelva. Dado que la devolución de llamada y el servicio deben realizar llamadas de salida de solicitud/respuesta antes de poder responder a la solicitud pendiente, las implementaciones se deben marcar con el comportamiento de ConcurrencyMode.Reentrant.
Configurar, compilar y ejecutar el ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.
Para ejecutar el ejemplo en una configuración de un solo equipo o de varios, siga las instrucciones de Ejecución de ejemplos de Windows Communication Foundation.
Muestra
Para ejecutar el ejemplo, compile los proyectos de servidor y cliente. A continuación, abra dos ventanas de comandos y cambie los directorios a los directorios <sample>\CS\Service\bin\debug y <sample>\CS\Client\bin\debug. A continuación, inicie el servicio al escribir service.exe
y, a continuación, invoque Client.exe con el valor inicial de los pasos pasados como argumento de entrada. Se muestra un resultado del ejemplo para 10 pasos.
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