Feche e anule recursos de liberação com segurança quando as conexões de rede caírem
O exemplo UsingUsing demonstra o uso dos Close
métodos e Abort
para limpar recursos ao usar um cliente tipado. A using
instrução causa exceções quando a conexão de rede não é robusta. Este exemplo é baseado na Introdução que implementa um serviço de calculadora. Neste exemplo, o cliente é um aplicativo de console (.exe) e o serviço é hospedado pelo IIS (Serviços de Informações da Internet).
Nota
O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.
Este exemplo mostra dois dos problemas comuns que ocorrem ao usar a instrução C# "usando" com clientes tipados, bem como o código que limpa corretamente após exceções.
A instrução C# "usando" resulta em uma chamada para Dispose
(). Isso é o mesmo Close
que (), que pode gerar exceções quando ocorre um erro de rede. Como a chamada para Dispose
() acontece implicitamente na chave de fechamento do bloco "usando", essa fonte de exceções provavelmente passará despercebida tanto pelas pessoas que escrevem o código quanto pela leitura do código. Isso representa uma fonte potencial de erros de aplicativo.
O primeiro problema, ilustrado DemonstrateProblemUsingCanThrow
no método, é que a chave de fechamento lança uma exceção e o código após a chave de fechamento não executa:
using (CalculatorClient client = new CalculatorClient())
{
...
} // <-- this line might throw
Console.WriteLine("Hope this code wasn't important, because it might not happen.");
Mesmo que nada dentro do bloco de uso lance uma exceção ou todas as exceções dentro do bloco de uso sejam capturadas, isso Console.WriteLine
pode não acontecer porque a chamada implícita Dispose
() na chave de fechamento pode lançar uma exceção.
O segundo problema, ilustrado DemonstrateProblemUsingCanThrowAndMask
no método, é outra implicação do lançamento de uma exceção pela cinta de fechamento:
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.
Como o Dispose
() ocorre dentro de um bloco "finalmente", o ApplicationException
nunca é visto fora do bloco de uso se o Dispose
() falhar. Se o código externo deve saber sobre quando ocorre ApplicationException
, a construção "usando" pode causar problemas mascarando essa exceção.
Finalmente, o exemplo demonstra como limpar corretamente quando ocorrem exceções no DemonstrateCleanupWithExceptions
. Isso usa um bloco try/catch para relatar erros e chamar Abort
. Consulte o Exemplo de exceções esperadas para obter mais detalhes sobre como capturar exceções de chamadas de cliente.
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Nota
A using
instrução e ServiceHost
: Muitos aplicativos de auto-hospedagem fazem pouco mais do que hospedar um serviço, e ServiceHost.Close
raramente lança uma exceção, para que tais aplicativos possam usar com segurança a using
instrução com ServiceHost
. No entanto, esteja ciente de que ServiceHost.Close
pode lançar um CommunicationException
, por isso, se a sua aplicação continuar após o fechamento do ServiceHost
, você deve evitar a using
declaração e seguir o padrão dado anteriormente.
Quando você executa o exemplo, as respostas e exceções da operação são exibidas na janela do console do cliente.
O processo do cliente executa três cenários, cada um dos quais tenta chamar Divide
. O primeiro cenário demonstra que o código está sendo ignorado devido a uma exceção de Dispose
(). O segundo cenário demonstra uma exceção importante sendo mascarada devido a uma exceção de Dispose
(). O terceiro cenário demonstra uma limpeza correta.
A saída esperada do processo do cliente é:
=
= 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.
Para configurar, compilar e executar o exemplo
Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.
Para criar a edição C# ou Visual Basic .NET da solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.
Para executar o exemplo em uma configuração de máquina única ou cruzada, siga as instruções em Executando os exemplos do Windows Communication Foundation.