Dela via


ConcurrencyMode Omåtervändande

Reentrant-exemplet visar nödvändigheten och konsekvenserna av att använda ConcurrencyMode.Reentrant för en tjänstimplementering. ConcurrencyMode.Reentrant innebär att tjänsten (eller återanropet) endast bearbetar ett meddelande vid en viss tidpunkt (analogt med ConcurencyMode.Single). För att säkerställa trådsäkerheten låser Windows Communication Foundation (WCF) bearbetningen InstanceContext av ett meddelande så att inga andra meddelanden kan bearbetas. I händelse av återinträdesläge låses InstanceContext upp precis innan tjänsten gör ett utgående samtal, vilket gör att det efterföljande samtalet, (som kan vara återinträde som visas i exemplet), kan få låset nästa gång det kommer in i tjänsten. För att demonstrera beteendet visar exemplet hur en klient och tjänst kan skicka meddelanden mellan varandra med hjälp av ett duplexkontrakt.

Kontraktet som definieras är ett duplex-kontrakt med metoden Ping som implementeras av tjänsten och återanropsmetoden Pong som implementeras av klienten. En klient anropar serverns Ping-metod med en räkneverk och initierar därmed anropet. Tjänsten kontrollerar om antalet fästingar inte är lika med 0 och anropar sedan återanropsmetoden Pong samtidigt som fästingantalet minskas. Detta görs med följande kod i exemplet.

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));
     }
}

Återanropets Pong implementering har samma logik som implementeringen Ping . Det innebär att den först kontrollerar om antalet tick inte är noll och sedan anropar Ping metoden på återanropskanalen (i det här fallet är det kanalen som användes för att skicka det ursprungliga Ping meddelandet) med räkningen av tick minskad med 1. När tidsräknaren når 0, returnerar metoden och avvecklar därmed alla svar tillbaka till den första anropet som klienten som initierade anropet gjorde. Detta visas i återanropsimplementeringen.

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));
    }
}

Både Ping och Pong metoderna är begäran/svar, vilket innebär att det första anropet till Ping inte återvänder förrän anropet till CallbackChannel<T>.Pong() återvänder. På klienten kan Pong-metoden inte returnera förrän nästa Ping-anrop som den har gjort returnerar. Eftersom både återanropet och tjänsten måste göra utgående begärande-/svarsanrop innan de kan svara för den väntande begäran, måste båda implementeringarna markeras med concurrencyMode.Reentrant-beteendet.

Så här konfigurerar du, skapar och kör exemplet

  1. Kontrollera att du har utfört One-Time installationsproceduren för Windows Communication Foundation-exempel.

  2. Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.

  3. Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.

Demonstrerar

Skapa klient- och serverprojekten för att köra exemplet. Öppna sedan två kommandofönster och ändra katalogerna till <exempel>\CS\Service\bin\debug och <sample>\CS\Client\bin\debug-kataloger. Starta sedan tjänsten genom att skriva service.exe och anropa sedan Client.exe med det initiala värdet av tick som skickas som indataargument. Ett exempel på utdata för 10 pulser visas.

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