Sdílet prostřednictvím


Bezpečné ukončení a přerušení prostředků vydaných verzí v době, kdy došlo k vyřazení síťových připojení

Ukázka usingUsing ukazuje použití Close a Abort metody k vyčištění prostředků při použití zadaného klienta. Příkaz using způsobí výjimky, když síťové připojení není robustní. Tato ukázka vychází ze služby Začínáme , která implementuje službu kalkulačky. V této ukázce je klient konzolovou aplikací (.exe) a služba je hostovaná Internetová informační služba (IIS).

Poznámka:

Postup nastavení a pokyny k sestavení pro tuto ukázku najdete na konci tohoto tématu.

Tato ukázka ukazuje dva běžné problémy, ke kterým dochází při použití příkazu "using" jazyka C# s typed klienty, a také kód, který správně vyčistí po výjimkách.

Výsledkem příkazu "using" jazyka C# je volání Dispose(). To je stejné jako Close(), což může vyvolat výjimky, když dojde k chybě sítě. Vzhledem k tomu, že volání Dispose() se implicitně provádí u uzavírací složené závorky bloku using, je pravděpodobné, že tento zdroj výjimek nepůjde nevšimnout jak tím, že lidé zapisují kód a čtou kód. Představuje potenciální zdroj chyb aplikace.

Prvním problémem, který je znázorněn v DemonstrateProblemUsingCanThrow metodě, je, že pravá složená závorka vyvolá výjimku a kód po uzavření složené závorky se nespustí:

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

I když nic uvnitř bloku using vyvolá výjimku nebo jsou zachyceny všechny výjimky uvnitř bloku using, nemusí dojít k tomu, Console.WriteLine protože implicitní Dispose() volání na uzavírací závorce může vyvolat výjimku.

Druhým problémem, který je znázorněn v DemonstrateProblemUsingCanThrowAndMask metodě, je další implikací uzavření složené závorky, která vyvolá výjimku:

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.

DisposeVzhledem k tomu, že se () vyskytuje uvnitř bloku "finally", ApplicationException není nikdy vidět mimo blok using, pokud Dispose() selže. Pokud kód mimo musí vědět o výskytu ApplicationException , konstruktor using může způsobit problémy maskováním této výjimky.

Nakonec ukázka ukazuje, jak správně vyčistit, když dojde k DemonstrateCleanupWithExceptionsvýjimkám . Používá blok try/catch k hlášení chyb a volání Abort. Další podrobnosti o zachycení výjimek z volání klientů najdete v ukázce očekávaných výjimek.

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

Poznámka:

Příkaz using a ServiceHost: Mnoho samohostingových aplikací dělá o něco víc než hostování služby, a ServiceHost.Close zřídka vyvolá výjimku, takže takové aplikace mohou bezpečně používat using příkaz s ServiceHost. Mějte však na paměti, že ServiceHost.Close může vyvolat chybu CommunicationException, takže pokud vaše aplikace pokračuje po zavření ServiceHost, měli byste se vyhnout using příkazu a dodržovat dříve zadaný vzor.

Při spuštění ukázky se odpovědi na operace a výjimky zobrazí v okně konzoly klienta.

Proces klienta spouští tři scénáře, z nichž každý se pokusí volat Divide. První scénář ukazuje přeskočení kódu kvůli výjimce ( Dispose). Druhý scénář ukazuje, že je důležitá výjimka maskovaná kvůli výjimce ( Dispose). Třetí scénář ukazuje správné vyčištění.

Očekávaný výstup z procesu klienta je následující:

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

Nastavení, sestavení a spuštění ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit edici C# nebo Visual Basic .NET řešení, postupujte podle pokynů v části Sestavení ukázek windows Communication Foundation.

  3. Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.