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.

Descriçã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. Se eles não concordarem, o canal de sessão pode falhar.

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

Nota

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 desabilitada) exibe a sessão da conexão TCP, se você ouvir o ICommunicationObject.Faulted evento no serviço ou no cliente, é provável que seja notificado rapidamente no caso de uma falha de 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 Usando 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 a vinculação especificada foram cumpridas, e o outro lado não ligou ICommunicationObject.Abort para o canal antes de ligar 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 tentativa, a conversa será bem-sucedida, a menos que uma exceção seja lançada. Normalmente, se uma exceção é lançada, a conversa é abortada.

Nota

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 obter mais informações, consulte Usar Fechar e Abortar para liberar recursos de cliente 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

Nota

Verificar o ICommunicationObject.State valor da propriedade é 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 um System.ServiceModel.Security.MessageSecurityExceptionarquivo . 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 Serviços unidirecionais.

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 a /asyncopção 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 Aplicativos cliente de camada intermediária.

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 aplicativos podem fazer uso de um inserido IInteractiveChannelInitializer de duas maneiras. O aplicativo cliente pode chamar uma ou ClientBase<TChannel>.DisplayInitializationUIIClientChannel.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 ele chamar algo diferente da primeira operação, uma exceção será lançada.

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

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

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

  3. Operações de chamada.

Recomenda-se que os aplicativos de qualidade de produção controlem o processo de interface do usuário 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.

Consulte também