ConcurrencyMode.Reentrant
Nell’esempio Reentrant vengono descritte la necessità e le implicazioni dell'utilizzo di ConcurrencyMode.Reentrant in un'implementazione del servizio. ConcurrencyMode.Reentrant implica che il servizio (o callback) elabora solo uno messaggio a un'ora specificata (come per ConcurencyMode.Single
). Per garantire la thread safety, Windows Communication Foundation (WCF) evita che InstanceContext
elabori un messaggio in modo che non sia possibile elaborare altri messaggi. Nel caso della modalità Reentrant, InstanceContext
viene sbloccato poco prima che il servizio effettui una chiamata in uscita, consentendo alla chiamata successiva (che può essere rientrante, come illustrato nell'esempio) di eseguire il blocco la prossima volta che entra nel servizio. Per descrivere il comportamento, nell'esempio viene illustrato come un client e un servizio possono inviarsi messaggi utilizzando un contratto duplex.
Il contratto definito è un contratto duplex con il metodo Ping
implementato dal servizio e il metodo di callback Pong
implementato dal client. Un client richiama il metodo Ping
del server con un conteggio di tick, avviando così la chiamata. Il servizio verifica se il conteggio di tick non è uguale a 0 e richiama quindi il metodo Pong
del callback, mentre esegue il decremento del conteggio di tick. Questa operazione viene eseguita nell'esempio di codice seguente:
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));
}
}
L'implementazione Pong
del callback è dotata della stessa logica dell'implementazione Ping
. Ovvero, controlla se il conteggio non è zero, quindi richiama il metodo Ping
sul canale di callback (in questo caso il canale utilizzato per inviare il messaggio Ping
originale) con il conteggio decrementato di 1. Nel momento in cui il conteggio raggiunge lo zero, il metodo viene completato, annullando così il wrapping di tutte le risposte fino alla prima chiamata effettuata dal client che ha avviato la chiamata. Questa operazione viene illustrata nell'implementazione del callback.
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));
}
}
Entrambi i metodi Ping
e Pong
sono di tipo request/reply, il che significa che la prima chiamata a Ping
non viene restituita finché non viene restituita la chiamata a CallbackChannel<T>.Pong()
. Nel client, il metodo Pong
non può essere completato finché non viene restituita la chiamata Ping
successiva. Poiché il callback e il servizio devono eseguire chiamate in uscita di tipo request/reply prima che possano rispondere alla richiesta in sospeso, entrambi le implementazioni devono essere contrassegnate dal comportamento ConcurrencyMode.Reentrant.
Per impostare, compilare ed eseguire l'esempio
Assicurarsi di aver eseguito la Procedura di installazione singola per gli esempi di Windows Communication Foundation.
Per compilare l'edizione in C# o Visual Basic .NET della soluzione, seguire le istruzioni in Building the Windows Communication Foundation Samples.
Per eseguire l'esempio in un solo computer o tra computer diversi, seguire le istruzioni in Esecuzione degli esempi di Windows Communication Foundation.
Dimostra
Per eseguire l'esempio, compilare i progetti del client e del server. Aprire quindi due finestre di comando e impostare le directory su \CS\Service\bin\debug <di esempio> e \CS\Client\bin\debug <di esempio>. Avviare il servizio digitando service.exe
e richiamare quindi Client.exe con il valore iniziale di tick passato come argomento di input. Viene illustrato un esempio di output per tick.
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