Partilhar via


Acessando serviços usando um cliente

Os aplicativos cliente devem criar, configurar e usar objetos de cliente ou canal WCF para se comunicar com serviços. O tópico Visão geral do cliente WCF fornece uma visão geral dos objetos e etapas envolvidos na criação de objetos básicos de cliente e canal e usá-los.

Este tópico fornece informações detalhadas sobre alguns dos problemas com aplicativos cliente e objetos cliente e canal que podem ser úteis dependendo do seu cenário.

Visão geral

Este tópico descreve o comportamento e problemas relacionados a:

  • Tempo de vida do canal e da sessão.

  • Tratamento de exceções.

  • Compreender os problemas de bloqueio.

  • Inicializando canais interativamente.

Tempo de vida do canal e da sessão

Os aplicativos do Windows Communication Foundation (WCF) incluem duas categorias de canais, datagrama e sessão.

Um canal de datagrama é um canal no qual todas as mensagens não estão correlacionadas. Com um canal de datagrama, se uma operação de entrada ou saída falhar, a próxima operação normalmente não é afetada e o mesmo canal pode ser reutilizado. Por causa disso, os canais de datagrama normalmente não falham.

Os canais de sessão , no entanto, são canais com uma conexão com o outro ponto de extremidade. As mensagens numa sessão de um lado estão sempre correlacionadas com a mesma sessão do outro lado. Além disso, ambos os participantes de uma sessão devem concordar que os requisitos de sua conversa foram atendidos para que essa sessão seja considerada bem-sucedida. Caso não consigam chegar a um acordo, o canal com sessão pode apresentar uma falha.

Abra clientes explícita ou implicitamente chamando a primeira operação.

Observação

Tentar detetar explicitamente canais de sessão com defeito normalmente não é útil, porque quando você é notificado depende da implementação da sessão. Por exemplo, como o System.ServiceModel.NetTcpBinding (com a sessão confiável desativada) exibe a sessão da conexão TCP, se ouvir o evento ICommunicationObject.Faulted no serviço ou no cliente, é provável que seja notificado rapidamente no caso de uma interrupção na rede. Mas sessões confiáveis (estabelecidas por ligações nas quais o System.ServiceModel.Channels.ReliableSessionBindingElement está habilitado) são projetadas para isolar os serviços de pequenas falhas de rede. Se a sessão puder ser restabelecida dentro de um período de tempo razoável, a mesma vinculação — configurada para sessões confiáveis — poderá não falhar até que a interrupção continue por um longo período de tempo.

A maioria das ligações fornecidas pelo sistema (que expõem canais à camada de aplicativo) usa sessões por padrão, mas o System.ServiceModel.BasicHttpBinding não. Para obter mais informações, consulte Utilizando Sessões.

O uso adequado das sessões

As sessões fornecem uma maneira de saber se toda a troca de mensagens está concluída e se ambos os lados a consideraram bem-sucedida. Recomenda-se que um aplicativo de chamada abra o canal, use-o e feche o canal dentro de um bloco de tentativa. Se um canal de sessão estiver aberto e o ICommunicationObject.Close método for chamado uma vez, e essa chamada retornar com êxito, a sessão foi bem-sucedida. Bem-sucedido, neste caso, significa que todas as garantias de entrega especificadas na vinculação foram cumpridas e que o outro lado não chamou ICommunicationObject.Abort no canal antes de chamar Close.

A seção a seguir fornece um exemplo dessa abordagem de cliente.

Tratamento de exceções

Lidar com exceções em aplicativos cliente é simples. Se um canal for aberto, usado e fechado dentro de um bloco de código try, a conversa será bem-sucedida, a menos que uma exceção ocorra. Normalmente, se uma exceção é lançada, a conversa é abortada.

Observação

O uso da using instrução (Using no Visual Basic) não é recomendado. Isso ocorre porque o using final da instrução pode causar exceções que podem mascarar outras exceções que você pode precisar saber. Para mais informações, consulte Como usar Fechar e Abortar para libertar recursos de clientes WCF.

O exemplo de código a seguir mostra o padrão de cliente recomendado usando um bloco try/catch e não a using instrução.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    SampleServiceClient wcfClient = new SampleServiceClient();
    try
    {
      // Making calls.
      Console.WriteLine("Enter the greeting to send: ");
      string greeting = Console.ReadLine();
      Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));

      Console.WriteLine("Press ENTER to exit:");
      Console.ReadLine();

      // Done with service.
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException<GreetingFault> greetingFault)
    {
      Console.WriteLine(greetingFault.Detail.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException unknownFault)
    {
      Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
      Console.ReadLine();
      wcfClient.Abort();
    }
  }
}

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
    Public Shared Sub Main()
        ' Picks up configuration from the config file.
        Dim wcfClient As New SampleServiceClient()
        Try
            ' Making calls.
            Console.WriteLine("Enter the greeting to send: ")
            Dim greeting As String = Console.ReadLine()
            Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

            Console.WriteLine("Press ENTER to exit:")
            Console.ReadLine()

            ' Done with service. 
            wcfClient.Close()
            Console.WriteLine("Done!")
        Catch timeProblem As TimeoutException
            Console.WriteLine("The service operation timed out. " & timeProblem.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch greetingFault As FaultException(Of GreetingFault)
            Console.WriteLine(greetingFault.Detail.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch unknownFault As FaultException
            Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch commProblem As CommunicationException
            Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
            Console.ReadLine()
            wcfClient.Abort()
        End Try
    End Sub
End Class

Observação

Verificar o valor da propriedade ICommunicationObject.State é uma condição de corrida e não é recomendado para determinar se deve reutilizar ou fechar um canal.

Os canais de datagrama nunca falham, mesmo que ocorram exceções quando são fechados. Além disso, os clientes não duplex que não conseguem autenticar usando uma conversa segura normalmente lançam uma exceção System.ServiceModel.Security.MessageSecurityException. No entanto, se o cliente duplex usando uma conversa segura não conseguir autenticar, o cliente receberá um System.TimeoutException em vez disso.

Para obter informações mais completas sobre como trabalhar com informações de erro no nível do aplicativo, consulte Especificando e manipulando falhas em contratos e serviços. Exceções esperadas descreve as exceções esperadas e mostra como lidar com elas. Para obter mais informações sobre como lidar com erros ao desenvolver canais, consulte Manipulando exceções e falhas.

Bloqueio e desempenho do cliente

Quando um aplicativo chama de forma síncrona uma operação solicitação-resposta, o cliente bloqueia até que um valor de retorno seja recebido ou uma exceção (como um System.TimeoutException) seja lançada. Esse comportamento é semelhante ao comportamento local. Quando um aplicativo invoca de forma síncrona uma operação em um objeto ou canal de cliente WCF, o cliente não retorna até que a camada de canal possa gravar os dados na rede ou até que uma exceção seja lançada. E embora o padrão de troca de mensagens unidirecionais (especificado marcando uma operação com OperationContractAttribute.IsOneWay definido como true) possa tornar alguns clientes mais responsivos, as operações unidirecionais também podem bloquear, dependendo da vinculação e das mensagens que já foram enviadas. As operações unidirecionais são apenas sobre a troca de mensagens, nem mais nem menos. Para obter mais informações, consulte One-Way Services.

Grandes blocos de dados podem retardar o processamento do cliente, independentemente do padrão de troca de mensagens. Para entender como lidar com esses problemas, consulte Large Data and Streaming.

Se seu aplicativo deve fazer mais trabalho enquanto uma operação é concluída, você deve criar um par de método assíncrono na interface do contrato de serviço que seu cliente WCF implementa. A maneira mais fácil de fazer isso é usar o /async switch na ServiceModel Metadata Utility Tool (Svcutil.exe). Para obter um exemplo, consulte Como chamar operações de serviço de forma assíncrona.

Para obter mais informações sobre como aumentar o desempenho do cliente, consulte Middle-Tier aplicativos cliente.

Permitindo que o usuário selecione credenciais dinamicamente

A IInteractiveChannelInitializer interface permite que os aplicativos exibam uma interface de usuário que permite ao usuário escolher credenciais com as quais um canal é criado antes do início dos temporizadores de tempo limite.

Os desenvolvedores de aplicações podem fazer uso de um elemento inserido IInteractiveChannelInitializer de duas maneiras. O aplicativo cliente pode chamar ou ClientBase<TChannel>.DisplayInitializationUI ou IClientChannel.DisplayInitializationUI (ou uma versão assíncrona) antes de abrir o canal (a abordagem explícita) ou chamar a primeira operação (a abordagem implícita).

Se estiver usando a abordagem implícita, o aplicativo deve chamar a primeira operação em uma ClientBase<TChannel> ou IClientChannel extensão. Se for chamada qualquer operação diferente da primeira, uma exceção será lançada.

Se estiver usando a abordagem explícita, o aplicativo deve executar as seguintes etapas na ordem:

  1. Chame ClientBase<TChannel>.DisplayInitializationUI ou IClientChannel.DisplayInitializationUI (ou uma versão assíncrona).

  2. Quando os inicializadores retornarem, chame ou o método Open no objeto IClientChannel ou no objeto IClientChannel retornado da propriedade ClientBase<TChannel>.InnerChannel.

  3. Operações de chamada.

Recomenda-se que as aplicações de qualidade de produção controlem o processo de interface de utilizador adotando a abordagem explícita.

Os aplicativos que usam a abordagem implícita invocam os inicializadores da interface do usuário, mas se o usuário do aplicativo não responder dentro do período de tempo limite de envio da ligação, uma exceção será lançada quando a interface do usuário retornar.

Ver também