クライアント アプリケーションは、WCF クライアントまたはチャネル オブジェクトを作成、構成、および使用してサービスと通信する必要があります。 「WCF クライアントの概要」トピックでは、基本的なクライアント オブジェクトとチャネル オブジェクトの作成と使用に関連するオブジェクトと手順の概要について説明します。
このトピックでは、シナリオに応じて役立つ可能性のあるクライアント アプリケーションとクライアント オブジェクトとチャネル オブジェクトに関するいくつかの問題について詳しく説明します。
概要
このトピックでは、次に関連する動作と問題について説明します。
チャネルとセッションの有効期間。
例外の処理。
ブロックの問題について。
チャネルを対話形式で初期化する。
チャネルとセッションの有効期間
Windows Communication Foundation (WCF) アプリケーションには、データグラムとセッションフルの 2 つのカテゴリのチャネルが含まれています。
データグラム チャネルは、すべてのメッセージが相関のないチャネルです。 データグラム チャネルでは、入力操作または出力操作が失敗した場合、通常、次の操作は影響を受けず、同じチャネルを再利用できます。 このため、通常、データグラム チャネルは障害を発生しません。
ただし、セッションフル チャネルは、他のエンドポイントへの接続を持つチャネルです。 一方の側のセッション内のメッセージは、常に他方の側の同じセッションと関連付けられます。 さらに、セッションの両方の参加者は、そのセッションが成功したと見なされるために、会話の要件が満たされていることに同意する必要があります。 同意できない場合は、セッションフル チャネルに障害が発生する可能性があります。
最初の操作を呼び出して、クライアントを明示的または暗黙的に開きます。
注
エラーが発生したセッションフル チャネルを明示的に検出することは、通常は役に立ちません。通知を受けるタイミングはセッションの実装によって異なるためです。 たとえば、(信頼できるセッションが無効になっている) System.ServiceModel.NetTcpBinding が TCP 接続のセッションを表示するため、サービスまたはクライアントで ICommunicationObject.Faulted イベントをリッスンすると、ネットワーク障害が発生した場合にすぐに通知を受け取る可能性があります。 ただし、信頼できるセッション ( System.ServiceModel.Channels.ReliableSessionBindingElement が有効になっているバインドによって確立されます) は、小規模なネットワーク障害からサービスを絶縁するように設計されています。 セッションを妥当な時間内に再確立できる場合、信頼できるセッション用に構成された同じバインドは、中断が長期間続くまで失敗しない可能性があります。
システム提供のバインディング (アプリケーション層にチャネルを公開する) のほとんどは既定でセッションを使用しますが、 System.ServiceModel.BasicHttpBinding では使用されません。 詳細については、「セッションの 使用」を参照してください。
セッションの適切な使用
セッションは、メッセージ交換全体が完了したかどうか、および両方の側が成功したと見なしたかどうかを知る方法を提供します。 呼び出し元のアプリケーションがチャネルを開き、それを使用して、1 つの try ブロック内のチャネルを閉じておくことをお勧めします。 セッション チャネルが開き、 ICommunicationObject.Close メソッドが 1 回呼び出され、その呼び出しが正常に返された場合、セッションは成功しました。 この場合、成功とは、指定されたバインディングが満たされたことをすべての配信で保証し、もう一方の側がチャネルで ICommunicationObject.Abort を呼び出さなかったことを意味 Close。
次のセクションでは、このクライアント アプローチの例を示します。
例外の処理
クライアント アプリケーションでの例外の処理は簡単です。 try ブロック内でチャネルが開き、使用され、閉じられた場合、例外がスローされない限り、会話は成功します。 通常、例外がスローされた場合、会話は中止されます。
注
using
ステートメント (Visual Basic のUsing
) の使用は推奨されません。 これは、 using
ステートメントの末尾によって例外が発生し、知る必要がある他の例外をマスクする可能性があるためです。 詳細については、「 閉じて中止を使用して WCF クライアント リソースを解放する」を参照してください。
次のコード例は、 using
ステートメントではなく、try/catch ブロックを使用して推奨されるクライアント パターンを示しています。
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 サービス」を参照してください。
大きなデータ チャンクでは、メッセージ交換パターンに関係なく、クライアントの処理が遅くなる可能性があります。 これらの問題を処理する方法については、「 大規模なデータとストリーミング」を参照してください。
操作の完了時にアプリケーションでさらに多くの作業を行う必要がある場合は、WCF クライアントが実装するサービス コントラクト インターフェイスに非同期メソッド ペアを作成する必要があります。 これを行う最も簡単な方法は、ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) で /async
スイッチを使用することです。 例については、「 方法: サービス操作を非同期的に呼び出す」を参照してください。
クライアント パフォーマンスの向上の詳細については、「 Middle-Tier クライアント アプリケーション」を参照してください。
ユーザーが資格情報を動的に選択できるようにする
IInteractiveChannelInitializer インターフェイスを使用すると、タイムアウト タイマーが開始する前にチャネルを作成する資格情報をユーザーが選択できるユーザー インターフェイスをアプリケーションに表示できます。
アプリケーション開発者は、挿入された IInteractiveChannelInitializer を 2 つの方法で利用できます。 クライアント アプリケーションは、チャネルを開く前に ClientBase<TChannel>.DisplayInitializationUI または IClientChannel.DisplayInitializationUI (または非同期バージョン) を呼び出すか ( 明示的 なアプローチ)、または最初の操作 ( 暗黙的な アプローチ) を呼び出すことができます。
暗黙的なアプローチを使用する場合、アプリケーションは、 ClientBase<TChannel> または IClientChannel 拡張機能に対して最初の操作を呼び出す必要があります。 最初の操作以外のものを呼び出すと、例外がスローされます。
明示的なアプローチを使用する場合、アプリケーションは次の手順を順番に実行する必要があります。
ClientBase<TChannel>.DisplayInitializationUIまたはIClientChannel.DisplayInitializationUI (または非同期バージョン) を呼び出します。
初期化子が返されたら、IClientChannel オブジェクトまたは ClientBase<TChannel>.InnerChannel プロパティから返されたIClientChannel オブジェクトに対して、Open メソッドを呼び出します。
呼び出し操作。
運用環境の品質のアプリケーションでは、明示的なアプローチを採用してユーザー インターフェイス プロセスを制御することをお勧めします。
暗黙的なアプローチを使用するアプリケーションは、ユーザー インターフェイス初期化子を呼び出しますが、アプリケーションのユーザーがバインディングの送信タイムアウト期間内に応答できない場合は、ユーザー インターフェイスが返されるときに例外がスローされます。