Partilhar via


Feche e interrompa a libertação de recursos com segurança quando as conexões de rede falharem.

O UsingUsing sample demonstra como usar os métodos Close 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 no Getting Started, 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 demonstra dois dos problemas comuns que ocorrem ao utilizar a instrução C# "using" com clientes tipados, além de apresentar código que realiza a limpeza corretamente após exceções.

A instrução "using" de C# resulta numa chamada para Dispose(). É igual a Close(), que pode gerar exceções quando ocorre um erro de rede. Como a chamada para Dispose() acontece implicitamente na chave de fechamento da declaração "using", esta fonte de exceções provavelmente será ignorada tanto por quem escreve o código quanto por quem o lê. Isso representa uma fonte potencial de erros de aplicativo.

O primeiro problema, ilustrado no método DemonstrateProblemUsingCanThrow, é que a chaveta de fechamento lança uma exceção e o código após a chaveta de fechamento não é executado.

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 no método DemonstrateProblemUsingCanThrowAndMask, é outra implicação do lançamento de uma exceção pela chaveta 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 "finally", o ApplicationException nunca é visto fora do bloco "using" se o Dispose() falhar. Se o código externo precisa estar ciente de quando ApplicationException ocorre, a construção "usando" pode causar problemas ao mascarar 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 Exceções Esperadas para obter mais detalhes sobre a captura de exceções nas chamadas do 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

  1. Certifique-se de ter executado o procedimento de configuração única dos exemplos do Windows Communication Foundation.

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

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