ConcurrencyMode Reentrant
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 Reentrant-läge InstanceContext
låses upp precis innan tjänsten gör ett utgående anrop så att det efterföljande anropet (som kan återaktiveras som visas i exemplet) får 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 ett antal fästingar 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 kontrollerar om antalet tick inte är noll och anropar Ping
sedan metoden på återanropskanalen (i det här fallet är det kanalen som användes för att skicka det ursprungliga Ping
meddelandet) med tickantalet minskat med 1. När fästingantalet når 0 returnerar metoden och tar därmed bort alla svar till det första anropet som gjordes av klienten som initierade anropet. 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));
}
}
Ping
Både metoderna och Pong
är begäran/svar, vilket innebär att det första anropet till Ping
inte returneras förrän anropet till CallbackChannel<T>.Pong()
returnerar. På klienten Pong
kan metoden inte returneras förrän nästa Ping
anrop som den gjorde 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
Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.
Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.
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.
Demonstrationer
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 service.exe
skriva och anropa sedan Client.exe med det initiala värdet för fästingar som skickas som indataargument. Ett exempel på utdata för 10 tick 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