Dela via


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.

DisposeEftersom () inträffar i ett "äntligen"-block ApplicationException visas aldrig utanför användningsblocket Disposeom () 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 ServiceHostbö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

  1. Kontrollera att du har utfört engångsinstallationsproceduren 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.