Поделиться через


Доступ к службам с помощью клиента

Клиентские приложения должны создавать, настраивать и использовать объекты клиента ИЛИ канала WCF для взаимодействия со службами. В разделе обзора клиента WCF представлены общие сведения об объектах и шагах, связанных с созданием базовых объектов клиента и канала и их использованием.

В этом разделе содержатся подробные сведения о некоторых проблемах с клиентскими приложениями и объектами клиента и канала, которые могут быть полезны в зависимости от вашего сценария.

Обзор

В этом разделе описывается поведение и проблемы, связанные с:

  • Время существования канала и сеанса.

  • Обработка исключений.

  • Понимание блокирующих проблем.

  • Инициализация каналов в интерактивном режиме.

Время существования канала и сеанса

Приложения Windows Communication Foundation (WCF) включают две категории каналов, диаграммы данных и сеансов.

Канал диаграммы данных — это канал, в котором все сообщения некоррелируются. При использовании канала датаграмм, если операция ввода-вывода завершается ошибкой, следующая операция обычно не будет затронута, и тот же канал может быть использован повторно. Из-за этого каналы дейтаграмм обычно не дают сбоя.

Однако сеансовые каналы являются каналами с подключением к другой конечной точке. Сообщения в сеансе на одной стороне всегда коррелируются с тем же сеансом на другой стороне. Кроме того, оба участника сессии должны согласиться с тем, что требования их беседы были выполнены для того, чтобы этот сеанс считался успешным. Если они не могут прийти к согласию, канал сеансов может выйти из строя.

Открытие клиентских соединений явно или неявно путем выполнения первой операции.

Замечание

Попытка явно обнаружить неисправные сеансовые каналы обычно не полезна, так как когда вы получаете уведомление, это зависит от реализации сеанса. Например, поскольку System.ServiceModel.NetTcpBinding (при отключенном надежном сеансе) делает видимым сеанс TCP-подключения, если вы прослушиваете событие ICommunicationObject.Faulted в службе или клиенте, вы, скорее всего, будете быстро уведомлены в случае сбоя сети. Но надежные сеансы (установленные привязками, в которых System.ServiceModel.Channels.ReliableSessionBindingElement включена) предназначены для изоляции служб от небольших сбоев сети. Если сеанс может быть восстановлен в течение разумного периода времени, то та же привязка, настроенная для надежных сеансов, может не привести к сбоям, пока прерывание не продолжится в течение длительного периода времени.

Большинство системных привязок (которые предоставляют каналы на уровне приложения) используют сеансы по умолчанию, но System.ServiceModel.BasicHttpBinding не использует их. Дополнительные сведения см. в разделе "Использование сеансов".

Правильное использование сеансов

Сеансы предоставляют способ узнать, завершен ли весь обмен сообщениями, и если обе стороны считают его успешным. Рекомендуется, чтобы вызывающее приложение открыло канал, использовало его и закрыло канал внутри одного блока try. Если канал сеанса открыт, и ICommunicationObject.Close метод вызывается один раз, и этот вызов возвращается успешно, сеанс был успешно выполнен. Успех в этом случае означает, что все гарантии доставки, предусмотренные указанной привязкой, были выполнены, и другая сторона не вызывала ICommunicationObject.Abort на канале до вызова Close.

В следующем разделе приведен пример этого подхода клиента.

Обработка исключений

Обработка исключений в клиентских приложениях проста. Если канал открыт, используется и закрывается внутри блока try, операция выполнена успешно, если исключение не возникает. Как правило, если исключение выбрасывается, разговор прерывается.

Замечание

Использование инструкции using (Using в Visual Basic) не рекомендуется. Это связано с тем, что конец инструкции using может вызвать исключения, которые могут маскировать другие исключения, о которых может потребоваться знать. Для получения дополнительной информации, см. Использование методов Close и Abort для освобождения ресурсов клиентских приложений WCF.

В следующем примере кода показан рекомендуемый шаблон клиента с помощью блока try/catch, а не инструкции using .

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

Замечание

Проверка значения ICommunicationObject.State свойства является условием гонки и не рекомендуется определить, следует ли повторно использовать или закрыть канал.

Каналы датаграмм никогда не выходят из строя, даже если происходят исключения при их закрытии. Кроме того, не-дуплексные клиенты, которые не проходят проверку подлинности с помощью безопасной беседы, обычно вызывают исключение System.ServiceModel.Security.MessageSecurityException. Однако если дуплексный клиент, использующий безопасную беседу, не проходит проверку подлинности, клиент получает System.TimeoutException вместо этого.

Дополнительные сведения о работе с сведениями об ошибках на уровне приложения см. в разделе "Указание и обработка ошибок в контрактах и службах". Ожидаемые исключения описывают ожидаемые исключения и показано, как их обрабатывать. Дополнительные сведения об обработке ошибок при разработке каналов см. в разделе "Обработка исключений и сбоев".

Блокировка клиента и производительность

Когда приложение синхронно вызывает операцию запроса-ответа, клиент блокируется до тех пор, пока не будет получено возвращаемое значение или возникнет исключение (например, System.TimeoutException). Это поведение аналогично локальному поведению. Когда приложение синхронно вызывает операцию в клиентском объекте или канале WCF, клиент не возвращается до тех пор, пока уровень канала не сможет записать данные в сеть или до тех пор, пока исключение не будет создано. И хотя односторонняя схема обмена сообщениями (указанная путем маркировки операции с OperationContractAttribute.IsOneWay установленным значением true) может сделать некоторых клиентов более адаптивными, односторонние операции также могут блокироваться в зависимости от привязки и того, какие сообщения уже отправлены. Односторонняя операция относится только к обмену сообщениями, больше и не меньше. Дополнительные сведения см. в разделе One-Way Services.

Большие блоки данных могут замедлить обработку клиента независимо от того, какой шаблон обмена сообщениями. Сведения об обработке этих проблем см. в разделе "Большие данные" и "Потоковая передача".

Если приложение должно сделать больше работы во время выполнения операции, необходимо создать пару асинхронных методов в интерфейсе контракта службы, который реализует клиент WCF. Самый простой способ сделать это — использовать /async переключатель в средстве служебной программы метаданных ServiceModel (Svcutil.exe). Пример см. в статье "Практическое руководство: как асинхронно выполнять операции службы".

Чтобы получить больше информации о повышении производительности клиентских приложений, см. Middle-Tier Клиентские приложения.

Включение динамического выбора учетных данных пользователем

Интерфейс IInteractiveChannelInitializer позволяет приложениям отображать пользовательский интерфейс, позволяющий пользователю выбирать учетные данные, с помощью которых создается канал до запуска таймеров времени ожидания.

Разработчики приложений могут использовать вставленный IInteractiveChannelInitializer двумя способами. Клиентское приложение может вызывать либо ClientBase<TChannel>.DisplayInitializationUI, либо IClientChannel.DisplayInitializationUI (или асинхронную версию), прежде чем открывать канал (явный подход) или вызывать первую операцию (неявный подход).

При использовании неявного подхода приложение должно вызвать первую операцию в ClientBase<TChannel> или IClientChannel расширении. Если он вызывает что-либо, отличное от первой операции, создается исключение.

Если используется явный подход, приложение должно выполнить следующие действия в порядке:

  1. Позвоните либо ClientBase<TChannel>.DisplayInitializationUI, либо IClientChannel.DisplayInitializationUI (или их асинхронная версия).

  2. При возврате инициализаторов вызовите метод либо на объекте Open, либо на объекте IClientChannel, возвращаемом из свойства IClientChannel.

  3. Операции вызова.

Рекомендуется, чтобы приложения промышленного уровня управляли процессом пользовательского интерфейса при помощи явного подхода.

Приложения, использующие неявный подход, вызывают инициализаторы пользовательского интерфейса, но если пользователь приложения не отвечает в течение периода ожидания отправки привязки, исключение возникает при возврате пользовательского интерфейса.

См. также