クライアントを使用したサービスへのアクセス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) アプリケーションには、データグラムとセッションフルという2つのカテゴリがあります。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. 呼び出し側のアプリケーションでは、チャネルを開き、使用して、閉じるまでを 1 つの try ブロック内で処理することをお勧めします。It is recommended that a calling application open the channel, use it, and close the channel inside one try block. セッション チャネルが開いているときに、ICommunicationObject.Close メソッドを 1 回呼び出して、その呼び出しが正常に返された場合、セッションは成功しています。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ステートメント(Using Visual Basic) は使用しないことをお勧めします。Use 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. 詳細については、「 Close と Abort を使用して WCF クライアントリソースを解放する」を参照してください。For more information, see Use Close and Abort to release WCF client resources.

次のコード例は、using 文ではなく try/catch ブロックを使用する、推奨されるクライアント パターンを示しています。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.IsOneWaytrue に設定された操作をマークすることで指定される) では、クライアントの応答性が向上する可能性がありますが、バインディングや送信済みのメッセージによっては、一方向操作でもブロックが生じる場合があります。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 を 2 つの方法で利用できます。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