Procedura wielobieżna ConcurrencyMode
W przykładzie Reentrant przedstawiono konieczność i implikacje korzystania z funkcji ConcurrencyMode.Reentrant w implementacji usługi. ConcurrencyMode.Reentrant oznacza, że usługa (lub wywołanie zwrotne) przetwarza tylko jeden komunikat w danym momencie (analogiczny do ConcurencyMode.Single
). Aby zapewnić bezpieczeństwo wątków, program Windows Communication Foundation (WCF) blokuje przetwarzanie komunikatu InstanceContext
, aby nie można było przetworzyć żadnych innych komunikatów. W przypadku trybu InstanceContext
reentrant jest odblokowywane tuż przed wykonaniem wywołania wychodzącego, dzięki czemu kolejne wywołanie (które może być ponownie możliwe, jak pokazano w przykładzie), aby uzyskać blokadę przy następnym przejściu do usługi. Aby zademonstrować zachowanie, w przykładzie pokazano, jak klient i usługa mogą wysyłać komunikaty między sobą przy użyciu kontraktu dwustronnego.
Zdefiniowany kontrakt jest kontraktem dwudupleksowym z Ping
metodą zaimplementowaną przez usługę i metodą Pong
wywołania zwrotnego implementowanych przez klienta. Klient wywołuje metodę serwera Ping
z liczbą znaczników, inicjując wywołanie. Usługa sprawdza, czy liczba znaczników nie jest równa 0, a następnie wywołuje metodę wywołań zwrotnych Pong
podczas dekrementacji liczby znaczników. Jest to wykonywane za pomocą następującego kodu w przykładzie.
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));
}
}
Implementacja Pong
wywołania zwrotnego ma taką samą logikę jak implementacja Ping
. Oznacza to, że sprawdza, czy liczba znaczników nie jest równa zero, a następnie wywołuje Ping
metodę w kanale wywołania zwrotnego (w tym przypadku jest to kanał, który został użyty do wysłania oryginalnego Ping
komunikatu) z liczbą znaczników zdekrementowaną przez 1. Gdy liczba znaczników osiągnie wartość 0, metoda zwraca w ten sposób rozpasanie wszystkich odpowiedzi z powrotem do pierwszego wywołania wykonanego przez klienta, który zainicjował wywołanie. Jest to wyświetlane w implementacji wywołania zwrotnego.
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));
}
}
Metody i Pong
to żądanie/odpowiedź, co oznacza, że pierwsze wywołanie metody nie zwraca się do momentu zwrócenia wywołania CallbackChannel<T>.Pong()
Ping
.Ping
Na kliencie Pong
metoda nie może powrócić do momentu następnego Ping
wywołania, które dokonało zwrotów. Ponieważ zarówno wywołanie zwrotne, jak i usługa musi wysyłać wychodzące żądania/wywołania odpowiedzi, zanim będą mogły odpowiedzieć na oczekujące żądanie, obie implementacje muszą być oznaczone zachowaniem ConcurrencyMode.Reentrant.
Aby skonfigurować, skompilować i uruchomić przykład
Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.
Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).
Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.
Demonstracje
Aby uruchomić przykład, skompiluj projekty klienta i serwera. Następnie otwórz dwa okna poleceń i zmień katalogi na <sample>\CS\Service\bin\debug i <sample>\CS\Client\bin\debug. Następnie uruchom usługę, wpisując service.exe
, a następnie wywołaj Client.exe z początkową wartością znaczników przekazanych jako argument wejściowy. Wyświetlane są przykładowe dane wyjściowe dla 10 znaczników.
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