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

Клиентские приложения должны создавать, настраивать и использовать клиент или объекты канала WCF для взаимодействия со службами.Client applications must create, configure, and use WCF client or channel objects to communicate with services. В разделе Обзор клиента WCF содержатся общие сведения об объектах и шагах, связанных с созданием базовых объектов клиента и канала и их использовании.The WCF Client Overview topic provides an overview of the objects and steps involved in creating basic client and channel objects and using them.

В разделе приводится подробная информация о некоторых проблемах с приложениями клиента и объектами клиента и канала, которые могут пригодиться в зависимости от вашего сценария.This topic provides in-depth information about some of the issues with client applications and client and channel objects that may be useful depending upon your scenario.

ОбзорOverview

В разделе описаны поведение и проблемы, связанные со следующими пунктами.This topic describes behavior and issues relating to:

  • Каналы и время существования сеанса.Channel and session lifetimes.

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

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

  • Интерактивная инициализация каналов.Initializing channels interactively.

Каналы и время существования сеансаChannel and Session Lifetimes

Приложения Windows Communication Foundation (WCF) включают две категории каналов, датаграммы и сеансы.Windows Communication Foundation (WCF) applications includes two categories of channels, datagram and sessionful.

Канал датаграммы — это канал, в котором все сообщения не взаимосвязаны.A datagram channel is a channel in which all messages are uncorrelated. При использовании канала датаграммы на последующую операцию обычно не влияет то, что операция ввода или вывода не удалась, и тот же канал может быть использован повторно.With a datagram channel, if an input or output operation fails, the next operation is typically unaffected, and the same channel can be reused. По этой причине в каналах датаграмм обычно не возникает сбоев.Because of this, datagram channels typically do not fault.

Каналы с сеансом, однако, — это каналы с подключением к другой конечной точке.Sessionful channels, however, are channels with a connection to the other endpoint. Сообщения в сессии всегда коррелируют с таким же сеансом с другой стороны.Messages in a session on one side are always correlated with the same session on the other side. Кроме того, между участниками сеанса должно быть соглашение, описывающее требования к их диалогу, которые, для того чтобы сеанс считался успешным, должны быть удовлетворены.In addition, both participants in a session must agree that the requirements of their conversation were met for that session to be considered successful. Если такого соглашения между участниками нет, в канале сеанса может возникнуть ошибка.If they cannot agree, the sessionful channel may fault.

Откройте клиенты явно или неявно, вызвав первую операцию.Open clients explicitly or implicitly by calling the first operation.

Примечание

Попытка явно обнаружить каналы сеанса со сбоем обычно оказывается полезной, поскольку то, когда вы будете оповещены, зависит от реализации сеанса.Trying to explicitly detect faulted sessionful channels is not typically useful, because when you are notified depends upon the session implementation. Например, поскольку System.ServiceModel.NetTcpBinding (с отключенным надежным сеансом) покрывает сеанс связи TCP, если при ожидании передачи данных события ICommunicationObject.Faulted службы или клиента, желательно получить уведомление о сбое сети незамедлительно.For example, because the System.ServiceModel.NetTcpBinding (with the reliable session disabled) surfaces the session of the TCP connection, if you listen to the ICommunicationObject.Faulted event on the service or the client you are likely to be notified quickly in the event of a network failure. Но надежные сеансы (установленные привязками, в которых включен System.ServiceModel.Channels.ReliableSessionBindingElement) предназначены для изолирования служб от незначительных сбоев сети.But reliable sessions (established by bindings in which the System.ServiceModel.Channels.ReliableSessionBindingElement is enabled) are designed to insulate services from small network failures. Если сеанс может быть повторно установлен в течение допустимого периода времени, та же привязка, настроенная для надежных сеансов, может не дать сбой, пока прерывание не будет происходить в течение более продолжительного промежутка времени.If the session can be reestablished within a reasonable period of time, the same binding—configured for reliable sessions—might not fault until the interruption continued for a longer period of time.

Большинство предоставляемых системой привязок (экспонирующих каналы на уровень приложения) использует сеансы по умолчанию, однако System.ServiceModel.BasicHttpBinding этого не делает.Most of the system-provided bindings (which expose channels to the application layer) use sessions by default, but the System.ServiceModel.BasicHttpBinding does not. Дополнительные сведения см. в разделе Использование сеансов.For more information, see Using Sessions.

Правильное использование сеансовThe Proper Use of Sessions

Сеансы являются способом, с помощью которого можно узнать, полностью ли был завершен обмен сообщением и обе ли стороны считают его успешным.Sessions provide a way to know if the entire message exchange is complete, and if both sides considered it successful. Рекомендуется, чтобы вызывающее приложение открыло канал, использовало его и закрыло канал внутри одного блока try.It is recommended that a calling application open the channel, use it, and close the channel inside one try block. Если канал сеанса открыт и однократно вызван метод ICommunicationObject.Close, и данный вызов успешно возвращается, значит сеанс был успешен.If a session channel is open, and the ICommunicationObject.Close method is called once, and that call returns successfully, then the session was successful. "Успешный" в данном случае означает, что все гарантии доставки, заданные привязкой, были обеспечены и другая сторона не вызвала ICommunicationObject.Abort в канале перед вызовом Close.Successful in this case means that all delivery guarantees the binding specified were met, and the other side did not call ICommunicationObject.Abort on the channel before calling Close.

В следующем разделе показан пример данного подхода к клиенту.The following section provides an example of this client approach.

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

Обработка исключений в приложениях клиента является прямой.Handling exceptions in client applications is straightforward. Если канал открыт, использован и закрыт внутри одного блока try, диалог был успешен, кроме случая, если было выдано исключение.If a channel is opened, used, and closed inside a try block, then the conversation has succeeded, unless an exception is thrown. Обычно при выдаче исключения диалог прерывается.Typically, if an exception is thrown the conversation is aborted.

Примечание

Использование оператора (Using в Visual Basic) не рекомендуется. usingUse of the using statement (Using in Visual Basic) is not recommended. Это связано с тем, что конец оператора using может привести к исключениям, которые могут маскировать другие исключения, о которых вам, возможно, нужно знать.This is because the end of the using statement can cause exceptions that can mask other exceptions you may need to know about. Дополнительные сведения см. в разделе Использование закрытия и прерывания для освобождения ресурсов клиента WCF.For more information, see Use Close and Abort to release WCF client resources.

В приведенном ниже примере кода демонстрируется рекомендуемый шаблон клиента с помощью блока try/catch, а не с помощью оператора using.The following code example shows the recommended client pattern using a try/catch block and not the using statement.

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 является состоянием гонки и не рекомендуется для определения ситуации, когда канал можно использовать повторно или когда его нужно закрыть.Checking the value of the ICommunicationObject.State property is a race condition and is not recommended to determine whether to reuse or close a channel.

Каналы датаграммы не дают сбой, даже если исключения происходят при их закрытии.Datagram channels never fault even if exceptions occur when they are closed. Кроме того, недуплексные клиенты, которые не смогли пройти проверку с помощью защищенного диалога, как правило, создают исключение System.ServiceModel.Security.MessageSecurityException.In addition, non-duplex clients that fail to authenticate using a secure conversation typically throw a System.ServiceModel.Security.MessageSecurityException. Однако если дуплексному клиенту, использующему защищенный диалог, не удается пройти проверку, клиент получает вместо этого исключение System.TimeoutException.However if the duplex client using a secure conversation fails to authenticate, the client receives a System.TimeoutException instead.

Более полные сведения о работе со сведениями об ошибках на уровне приложения см. в разделе Указание и обработка ошибок в контрактах и службах.For more complete information about working with error information at the application level, see Specifying and Handling Faults in Contracts and Services. Ожидаемые исключения описывают ожидаемые исключения и показывает, как их справиться.Expected Exceptions describes expected exceptions and shows how to handle them. Дополнительные сведения об обработке ошибок при разработке каналов см. в разделе обработка исключений и ошибок.For more information about how to handle errors when developing channels, see Handling Exceptions and Faults.

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

Когда приложение синхронно вызывает операцию типа запрос-ответ, клиент блокируется до тех пор, пока не будет получено возвращаемое значение или создано исключение (такое как System.TimeoutException).When an application synchronously calls a request-reply operation, the client blocks until a return value is received or an exception (such as a System.TimeoutException) is thrown. Такое поведение аналогично локальному поведению.This behavior is similar to local behavior. Когда приложение синхронно вызывает операцию в клиентском объекте или канале WCF, клиент не возвращает значение, пока уровень канала не сможет записать данные в сеть или пока не будет вызвано исключение.When an application synchronously invokes an operation on a WCF client object or channel, the client does not return until the channel layer can write the data to the network or until an exception is thrown. И до тех пор, пока шаблон одностороннего обмена сообщениями (заданный маркировкой операции с помощью OperationContractAttribute.IsOneWay, которому присвоено значение true) повышает реакцию некоторых клиентов, односторонние операции также блокируются, в зависимости от привязки и того, какие сообщения уже были отправлены.And while the one-way message exchange pattern (specified by marking an operation with OperationContractAttribute.IsOneWay set to true) can make some clients more responsive, one-way operations can also block, depending upon the binding and what messages have already been sent. Односторонние операции относятся только к обмену сообщениями, не больше и не меньше.One-way operations are only about the message exchange, no more and no less. Дополнительные сведения см. в разделе односторонние службы.For more information, see One-Way Services.

Большие порции данных могут замедлить обработку клиента, независимо от шаблона обмена сообщениями.Large data chunks can slow client processing no matter what the message exchange pattern. Сведения об обработке этих проблем см. в разделе большие данные и потоковая передача.To understand how to handle these issues, see Large Data and Streaming.

Если приложение должно выполнять больше работы при завершении операции, следует создать пару асинхронных методов в интерфейсе контракта службы, который реализует клиент WCF.If your application must do more work while an operation completes, you should create an asynchronous method pair on the service contract interface that your WCF client implements. Самый простой способ сделать это — использовать /async параметр в средстве служебной программы метаданных ServiceModel (Svcutil. exe).The easiest way to do this is to use the /async switch on the ServiceModel Metadata Utility Tool (Svcutil.exe). Пример см. в статье Практическое руководство. Асинхронный вызов операций службы.For an example, see How to: Call Service Operations Asynchronously.

Дополнительные сведения о повышении производительности клиента см. в разделе клиентские приложения среднего уровня.For more information about increasing client performance, see Middle-Tier Client Applications.

Включение динамического выбора учетных данных пользователемEnabling the User to Select Credentials Dynamically

Интерфейс IInteractiveChannelInitializer позволяет приложениям отображать интерфейс пользователя, что позволяет пользователю выбирать учетные данные пользователя с которыми канал создается до того, как запустятся таймеры периода времени.The IInteractiveChannelInitializer interface enables applications to display a user interface that enables the user to choose credentials with which a channel is created before the timeout timers start.

Разработчики приложений могут использовать вставленный IInteractiveChannelInitializer двумя способами.Application developers can make use of an inserted IInteractiveChannelInitializer in two ways. ClientBase<TChannel>.DisplayInitializationUI Клиентское приложение может вызвать IClientChannel.DisplayInitializationUI либо (или) (или асинхронную версию) до открытия канала ( явный подход), либо вызвать первую операцию (неявный подход).The client application can call either ClientBase<TChannel>.DisplayInitializationUI or IClientChannel.DisplayInitializationUI (or an asynchronous version) prior to opening the channel (the explicit approach) or call the first operation (the implicit approach).

Если использовать неявный подход, то приложение должно вызвать первую операцию в расширении ClientBase<TChannel> или IClientChannel.If using the implicit approach, the application must call the first operation on a ClientBase<TChannel> or IClientChannel extension. Если приложение вызовет что-либо другое вместо первой операции, будет создано исключение.If it calls anything other than the first operation, an exception is thrown.

Если использовать явный подход, то приложение должно выполнить следующие шаги по порядку:If using the explicit approach, the application must perform the following steps in order:

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

  2. После возвращения инициализаторов вызвать либо метод Open в объекте IClientChannel, либо в объекте IClientChannel, возвращенном из свойства ClientBase<TChannel>.InnerChannel.When the initializers have returned, call either the Open method on the IClientChannel object or on the IClientChannel object returned from the ClientBase<TChannel>.InnerChannel property.

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

Рекомендуется, чтобы приложения для промышленного применения управляли процессом пользовательского интерфейса в соответствии с явным подходом.It is recommended that production-quality applications control the user-interface process by adopting the explicit approach.

Приложения, использующие неявный подход, вызывают инициализаторы интерфейса пользователя, но если пользователь приложения не сможет ответить в отведенный период времени привязки для отправки, то при возвращении пользовательского интерфейса создается исключение.Applications that use the implicit approach invoke the user-interface initializers, but if the user of the application fails to respond within the send timeout period of the binding, an exception is thrown when the user interface returns.

См. такжеSee also