Delen via


Resources veilig sluiten en afbreken wanneer netwerkverbindingen zijn verbroken

Het UsingUsing-voorbeeld laat zien hoe u resources Close kunt Abort opschonen met behulp van een getypte client. De using instructie veroorzaakt uitzonderingen wanneer de netwerkverbinding niet robuust is. Dit voorbeeld is gebaseerd op de Aan de slag die een rekenmachineservice implementeert. In dit voorbeeld is de client een consoletoepassing (.exe) en wordt de service gehost door Internet Information Services (IIS).

Notitie

De installatieprocedure en build-instructies voor dit voorbeeld bevinden zich aan het einde van dit onderwerp.

In dit voorbeeld ziet u twee van de veelvoorkomende problemen die optreden bij het gebruik van de C#-instructie 'using' met getypte clients, evenals code die correct wordt opgeschoond na uitzonderingen.

De C#-instructie 'using' resulteert in een aanroep naar Dispose(). Dit is hetzelfde als Close(), wat uitzonderingen kan veroorzaken wanneer er een netwerkfout optreedt. Omdat de aanroep van Dispose() impliciet plaatsvindt bij de afsluitende accolade van het blok 'using', is deze bron van uitzonderingen waarschijnlijk onopgemerkt door mensen die de code schrijven en de code lezen. Dit vertegenwoordigt een mogelijke bron van toepassingsfouten.

Het eerste probleem, geïllustreerd in de DemonstrateProblemUsingCanThrow methode, is dat de afsluitende accolade een uitzondering genereert en de code nadat de afsluitende accolade niet wordt uitgevoerd:

using (CalculatorClient client = new CalculatorClient())
{
    ...
} // <-- this line might throw
Console.WriteLine("Hope this code wasn't important, because it might not happen.");

Zelfs als er niets binnen het gebruiksblok een uitzondering genereert of alle uitzonderingen in het using-blok worden gevangen, kan dit Console.WriteLine niet gebeuren omdat de impliciete Dispose() aanroep bij de accolade sluiten een uitzondering kan veroorzaken.

Het tweede probleem, geïllustreerd in de DemonstrateProblemUsingCanThrowAndMask methode, is een andere implicatie van de afsluitende accolade die een uitzondering genereert:

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.

Omdat de Dispose() binnen een 'definitief' blok voorkomt, wordt het ApplicationException nooit buiten het using-blok gezien als de Dispose() mislukt. Als de code van buiten moet weten wanneer de ApplicationException gebeurtenis optreedt, kan de 'using'-constructie problemen veroorzaken door deze uitzondering te maskeren.

Ten slotte laat het voorbeeld zien hoe u correct kunt opschonen wanneer er uitzonderingen optreden in DemonstrateCleanupWithExceptions. Hierbij wordt een try/catch-blok gebruikt om fouten te melden en aan te roepen Abort. Zie het voorbeeld Verwachte uitzonderingen voor meer informatie over het vangen van uitzonderingen van clientoproepen.

try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

Notitie

De using instructie en ServiceHost: Veel zelfhostingtoepassingen doen weinig meer dan het hosten van een service en ServiceHost.Close genereren zelden een uitzondering, zodat dergelijke toepassingen de using instructie veilig kunnen gebruiken met ServiceHost. Houd er echter rekening mee dat ServiceHost.Close u een CommunicationException, dus als uw toepassing doorgaat na het sluiten van de ServiceHostinstructie, moet u de using instructie vermijden en het eerder opgegeven patroon volgen.

Wanneer u het voorbeeld uitvoert, worden de bewerkingsreacties en uitzonderingen weergegeven in het venster van de clientconsole.

Het clientproces voert drie scenario's uit, die elk proberen aan te roepen Divide. In het eerste scenario wordt code gedemonstreerd die wordt overgeslagen vanwege een uitzondering van Dispose(). In het tweede scenario ziet u een belangrijke uitzondering die wordt gemaskeerd vanwege een uitzondering van Dispose(). In het derde scenario ziet u de juiste opschoning.

De verwachte uitvoer van het clientproces is:

=
= 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.

Het voorbeeld instellen, compileren en uitvoeren

  1. Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.

  2. Als u de C# of Visual Basic .NET-editie van de oplossing wilt bouwen, volgt u de instructies in het bouwen van de Windows Communication Foundation-voorbeelden.

  3. Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Het uitvoeren van de Windows Communication Foundation-voorbeelden.