ConcurrencyMode Reentrant
L’exemple Reentrant illustre la nécessité d’utiliser ConcurrencyMode.Reentrant sur une implémentation de service et les implications d’une telle utilisation. ConcurrencyMode.Reentrant implique que le service (plus exactement l'interface de rappel) traite un seul message à la fois à un instant donné (traitement similaire à celui proposé par le mode ConcurencyMode.Single
). Pour garantir la sécurité des threads, Windows Communication Foundation (WCF) verrouille le InstanceContext
traitant un message afin qu’aucun autre message ne puisse être traité. En mode ConcurrencyMode.Reentrant, le contexte InstanceContext
est déverrouillé juste avant que le service n'effectue un appel externe, autorisant ainsi le prochain appel (lequel peut être réentrant tel qu'illustré dans l'exemple) et l'obtention du verrouillage lorsque le service reçoit la réponse à son appel. L'exemple illustre ce comportement en montrant comment un client et un service peuvent s'envoyer des messages en utilisant un contrat duplex.
Le contrat défini correspond à un contrat duplex dans lequel la méthode Ping
est implémentée par le service et la méthode de rappel Pong
par le client. Le client appelle la méthode Ping
du serveur à l'aide d'un compteur de cycles initiant par la même l'appel. Le service s'assure que la valeur du compteur de cycles n'est pas égale à zéro, puis appelle la méthode de rappel Pong
tout en décrémentant la valeur de ce compteur. Ce processus est illustré par l'exemple de code suivant.
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'implémentation de la méthode de rappel Pong
obéit à la même logique que l'implémentation de la méthode Ping
. Cela signifie, en d'autres termes, que cette méthode s'assure d'abord que le nombre de cycles n'est pas égal à zéro, puis qu'elle appelle la méthode Ping
sur le canal de rappel (dans ce cas, il s'agit du canal utilisé pour envoyer le message Ping
d'origine) tout en décrémentant la valeur du compteur de 1. Lorsque ce nombre atteint zéro, la méthode est retournée, désencapsulant toutes les réponses au premier appel initié par le client. Ce processus est illustré dans l'implémentation du rappel.
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));
}
}
Les méthodes Ping
et Pong
sont toutes deux du type demande-réponse, ce qui signifie que le premier appel de la méthode Ping
est retourné uniquement une fois l'appel de CallbackChannel<T>.Pong()
retourné. Sur le client, la méthode Pong
ne peut pas être retournée tant que le prochain appel de la méthode Ping
effectué n'est pas retourné. Le rappel et le service devant tous deux effectuer des appels externes de type demande-réponse avant de pouvoir répondre à la demande en attente, le comportement ConcurrencyMode.Reentrant doit être spécifié pour leurs implémentations respectives.
Pour configurer, générer et exécuter l'exemple
Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.
Pour générer l’édition C# ou Visual Basic .NET de la solution, conformez-vous aux instructions figurant dans Building the Windows Communication Foundation Samples.
Pour exécuter l’exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Exécution des exemples Windows Communication Foundation.
Illustre le
Pour exécuter l'exemple et générer les projets de client et de serveur. Ouvrez deux fenêtres de commande, puis remplacez les répertoires par les répertoires <exemple>\CS\Service\bin\debug et <exemple>\CS\Client\bin\debug. Démarrez ensuite le service en entrant service.exe
, puis appelez Client.exe en passant la valeur initiale du compteur de cycles sous forme d’argument d’entrée. Le code suivant illustre le résultat pour 10 cycles.
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