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.
Dispose
Vzhledem 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 DemonstrateCleanupWithExceptions
vý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
Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.
Pokud chcete sestavit edici C# nebo Visual Basic .NET řešení, postupujte podle pokynů v části Sestavení ukázek windows Communication Foundation.
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.