Stäng och avbryt versionsresurser på ett säkert sätt när nätverksanslutningarna har avbrutits
Exemplet UsingUsing visar hur du använder Close
metoderna och Abort
för att rensa resurser när du använder en typad klient. Instruktionen using
orsakar undantag när nätverksanslutningen inte är robust. Det här exemplet baseras på Komma igång som implementerar en kalkylatortjänst. I det här exemplet är klienten ett konsolprogram (.exe) och tjänsten hanteras av Internet Information Services (IIS).
Kommentar
Installationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av det här avsnittet.
Det här exemplet visar två av de vanliga problem som uppstår när du använder C#-instruktionen "using" med inskrivna klienter, samt kod som rensas korrekt efter undantag.
C#-instruktionen "using" resulterar i ett anrop till Dispose
(). Detta är samma som Close
(), som kan utlösa undantag när ett nätverksfel inträffar. Eftersom anropet till Dispose
() sker implicit vid den avslutande klammerparentesen i blocket "using" kommer den här källan med undantag sannolikt att gå obemärkt förbi både personer som skriver koden och läser koden. Detta representerar en potentiell källa till programfel.
Det första problemet, som illustreras i DemonstrateProblemUsingCanThrow
metoden, är att den avslutande klammerparentesen genererar ett undantag och koden efter att den avslutande klammerparentesen inte körs:
using (CalculatorClient client = new CalculatorClient())
{
...
} // <-- this line might throw
Console.WriteLine("Hope this code wasn't important, because it might not happen.");
Även om ingenting i användningsblocket genererar ett undantag eller om alla undantag i användningsblocket fångas, Console.WriteLine
kanske det inte händer eftersom det implicita Dispose
() anropet vid den avslutande klammerparentesen kan utlösa ett undantag.
Det andra problemet, som illustreras i DemonstrateProblemUsingCanThrowAndMask
metoden, är en annan implikation av det avslutande klammerparentesen som utlöser ett undantag:
using (CalculatorClient client = new CalculatorClient())
{
...
throw new ApplicationException("Hope this exception was not important, because "+
"it might be masked by the Close exception.");
} // <-- this line might throw an exception.
Dispose
Eftersom () inträffar i ett "äntligen"-block ApplicationException
visas aldrig utanför användningsblocket Dispose
om () misslyckas. Om koden utanför måste känna till när inträffar ApplicationException
kan "använda"-konstruktionen orsaka problem genom att maskera det här undantaget.
Slutligen visar exemplet hur du rensar korrekt när undantag inträffar i DemonstrateCleanupWithExceptions
. Detta använder ett try/catch-block för att rapportera fel och anropa Abort
. Mer information om att fånga undantag från klientanrop finns i exemplet förväntade undantag .
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Kommentar
Instruktionen using
och ServiceHost
: Många självvärdprogram gör inte mycket mer än att vara värd för en tjänst och ServiceHost.Close
genererar sällan ett undantag, så sådana program kan på ett säkert sätt använda -instruktionen using
med ServiceHost
. Tänk dock på att ServiceHost.Close
kan utlösa en CommunicationException
, så om programmet fortsätter efter att du har stängt ServiceHost
bör du undvika -instruktionen using
och följa det mönster som angavs tidigare.
När du kör exemplet visas åtgärdssvaren och undantagen i klientkonsolfönstret.
Klientprocessen kör tre scenarier som var och en försöker anropa Divide
. Det första scenariot visar att koden hoppas över på grund av ett undantag från Dispose
(). Det andra scenariot visar ett viktigt undantag som maskeras på grund av ett undantag från Dispose
(). Det tredje scenariot visar korrekt rensning.
Förväntade utdata från klientprocessen är:
=
= Demonstrating problem: closing brace of using statement can throw.
=
Got System.ServiceModel.CommunicationException from Divide.
Got System.ServiceModel.Security.MessageSecurityException
=
= Demonstrating problem: closing brace of using statement can mask other Exceptions.
=
Got System.ServiceModel.CommunicationException from Divide.
Got System.ServiceModel.Security.MessageSecurityException
=
= Demonstrating cleanup with Exceptions.
=
Calling client.Add(0.0, 0.0);
client.Add(0.0, 0.0); returned 0
Calling client.Divide(0.0, 0.0);
Got System.ServiceModel.CommunicationException from Divide.
Press <ENTER> to terminate client.
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.