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


Обращение к службам с использованием клиента

Клиентские приложения должны создавать, настраивать и использовать объекты клиента ИЛИ канала 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 может привести к исключениям, которые могут маскировать другие исключения, о которых вам, возможно, нужно знать. Дополнительные сведения см. в разделе "Закрыть" и "Прерывание" для выпуска клиентских ресурсов 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) повышает реакцию некоторых клиентов, односторонние операции также блокируются, в зависимости от привязки и того, какие сообщения уже были отправлены. Односторонние операции относятся только к обмену сообщениями, не больше и не меньше. Дополнительные сведения см. в разделе "Односторонняя служба".

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

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

Дополнительные сведения о повышении производительности клиента см. в разделе "Клиентские приложения среднего уровня".

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

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

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

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

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

  1. Вызывать либо ClientBase<TChannel>.DisplayInitializationUI, либо IClientChannel.DisplayInitializationUI (или асинхронную версию).

  2. После возвращения инициализаторов вызвать либо метод Open в объекте IClientChannel, либо в объекте IClientChannel, возвращенном из свойства ClientBase<TChannel>.InnerChannel.

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

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

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

См. также