セッション、インスタンス化、およびコンカレンシー
"セッション" とは、2 つのエンドポイント間で送信されるすべてのメッセージを相互に関連付けたものです。 "インスタンス化" とは、ユーザー定義のサービス オブジェクトとこれらのオブジェクトに関連する InstanceContext オブジェクトの有効期間を制御することです。 また、コンカレンシーは、InstanceContext で同時に実行されるスレッドの数の制御を表す用語です。
ここでは、これらの設定とその使用方法、各設定間のさまざまな相互作用について説明します。
セッション
サービス コントラクトによって ServiceContractAttribute.SessionMode プロパティが SessionMode.Requiredに設定されている場合、すべての呼び出し (つまり、呼び出しをサポートする、基になるメッセージ交換) を同じメッセージ交換の一部にする必要があります。 セッションが許可されるが必須ではないコントラクトの場合、クライアントは、接続した後にセッションを確立できます。また、セッションを確立しないままにしておくこともできます。 セッションが終了したのに、同じセッション ベースのチャネルでメッセージが送信されると、例外がスローされます。
WCF セッションには、次の主な概念的特徴があります。
呼び出し側アプリケーションによって明示的に開始および終了される。
セッション中に配信されたメッセージは、受信された順に処理される。
セッションはメッセージのグループを相互に関連付けて通信を行う。 ここで "相互に関連付ける" は、抽象的な意味を持ちます。 たとえば、あるセッション ベースのチャネルでは、共有ネットワーク接続に基づいてメッセージが相互に関連付けられる一方、別のセッション ベースのチャネルでは、メッセージ本文にある共有タグに基づいてメッセージが相互に関連付けられます。 セッションから派生可能な機能は、相互関連付けの性質によって異なります。
WCF セッションに関連付けられた一般的なデータ ストアはありません。
ASP.NET アプリケーションの System.Web.SessionState.HttpSessionState クラスに精通している場合は、この種のセッションと WCF セッションの間に次のような相違があることがわかります。
ASP.NET セッションは、常にサーバーによって開始される。
ASP.NET セッションは暗黙で順序指定されない。
ASP.NET セッションは、要求全体について一般的なデータ ストレージ機構を提供する。
クライアント アプリケーションとサービス アプリケーションでは、異なる方法でセッションと対話します。 クライアント アプリケーションはセッションを開始し、セッション内で送信されてきたメッセージの受信と処理を行います。 サービス アプリケーションでは、動作を追加するための機能拡張ポイントとしてセッションを使用できます。 これは InstanceContext を直接操作する、またはカスタムのインスタンス コンテキスト プロバイダーを実装することで可能になります。
インスタンス化
インスタンス化動作 ( ServiceBehaviorAttribute.InstanceContextMode プロパティを使用して設定します) は、受信メッセージに応答して InstanceContext を作成する方法を制御します。 既定では、各 InstanceContext は 1 つのユーザー定義サービス オブジェクトに関連付けられています。したがって、(既定では) InstanceContextMode プロパティを設定することによってもユーザー定義サービス オブジェクトのインスタンス化を制御できます。 インスタンス化モードは InstanceContextMode 列挙体によって定義されます。
次のインスタンス化モードを使用できます。
PerCall: 新しい InstanceContext (およびサービス オブジェクト) がクライアント要求ごとに作成されます。
PerSession: 新しい InstanceContext (およびサービス オブジェクト) が新しいクライアント セッションごとに作成され、そのセッションの有効期間中、保持されます (ただし、セッションをサポートするバインディングが必要です)。
Single: アプリケーションの有効期間中は、単一の InstanceContext (およびサービス オブジェクト) がすべてのクライアント要求を処理します。
既定の InstanceContextMode 値 (サービス クラスで明示的に設定された PerSession ) を次のコード例に示します。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorInstance
{
...
}
また、 ServiceBehaviorAttribute.InstanceContextMode プロパティは InstanceContext の解放頻度を制御しますが、 OperationBehaviorAttribute.ReleaseInstanceMode プロパティと ServiceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete プロパティはサービス オブジェクトの解放時期を制御します。
既知のシングルトン サービス
単一インスタンス サービス オブジェクトの 1 つのバリエーションとして、サービス オブジェクトをユーザーが自分で作成し、このオブジェクトを使用してサービス ホストを作成すると有用な場合があります。 そのためには、 ServiceBehaviorAttribute.InstanceContextMode プロパティを Single に設定するか、サービス ホストが開かれたときに例外をスローする必要があります。
このようなサービスを作成するには、 ServiceHost(Object, Uri[]) コンストラクターを使用します。 この方法は、シングルトン サービスが使用する特定のオブジェクト インスタンスを提供する場合に、カスタムの System.ServiceModel.Dispatcher.IInstanceContextInitializer を実装する代わりに使用できます。 サービス実装の型を作成することが困難な場合 (たとえば、パラメーターなしのコンストラクターが作成されない場合) は、このオーバーロードを使用できます。
このコンストラクターにオブジェクトを指定すると、Windows Communication Foundation (WCF) のインスタンス化動作に関するいくつかの機能が異なる動作をすることに注意してください。 たとえば、シングルトン オブジェクト インスタンスを指定しているときは、 InstanceContext.ReleaseServiceInstance を呼び出しても効果はありません。 他のインスタンス解放機構も、同様に無視されます。 ServiceHost は常に、すべての操作について OperationBehaviorAttribute.ReleaseInstanceMode プロパティが ReleaseInstanceMode.None に設定されているかのように動作します。
InstanceContext オブジェクトの共有
ユーザーが自ら関連付けを行うことにより、どの InstanceContext オブジェクトに、どのセッションフル チャネルまたは呼び出しを関連付けるかを制御することもできます。
コンカレンシー
コンカレンシーは、InstanceContext 内で同時にアクティブになるスレッドの数を制御します。 同時実行を制御するには、 ServiceBehaviorAttribute.ConcurrencyMode と ConcurrencyMode 列挙値を使用します。
選択可能なコンカレンシー モードは次の 3 つです。
Single: 各インスタンス コンテキストは、そのインスタンス コンテキスト内でメッセージを処理するスレッドを最大で一度に 1 つ持つことができます。 他のスレッドは、最初のスレッドがインスタンス コンテキストを使用し終えるまで、同じインスタンス コンテキストを使用できません。
Multiple: 各サービス インスタンスは、同時にメッセージを処理する複数のスレッドを持つことができます。 このコンカレンシー モードを使用するには、サービスの実装がスレッドセーフである必要があります。
Reentrant: 各サービス インスタンスは、一度に 1 つのメッセージを処理しますが、再入操作の呼び出しを受け入れます。 サービスは、WCF クライアント オブジェクトを通じて呼び出しを行う場合にのみ、この呼び出しを受け入れます。
注意
複数のスレッドを安全に使用するコードを理解し、適切に記述することが困難な場合もあります。 Multiple 値や Reentrant 値を使用する前に、これらのモード用にサービスが適切に設計されていることを確認してください。 詳細については、「ConcurrencyMode」を参照してください。
コンカレンシーの使用は、インスタンス化モードに関連します。 PerCall インスタンス化では、新しい InstanceContext によって各メッセージが処理され、複数のスレッドが InstanceContext でアクティブになることはないため、コンカレンシーには関連しません。
ConcurrencyMode プロパティを Multipleに設定するコード例を次に示します。
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorConcurrency
{
...
}
InstanceContext 設定と対話するセッション
セッションと InstanceContext は、コントラクト内の SessionMode 列挙値と、チャネルと特定のサービス オブジェクト間の関連付けを制御するサービス実装の ServiceBehaviorAttribute.InstanceContextMode プロパティ値の組み合わせに応じて、相互に作用します。
サービスの ServiceContractAttribute.SessionMode プロパティと ServiceBehaviorAttribute.InstanceContextMode プロパティの値の組み合わせが指定されているという条件で、セッションをサポートしている受信チャネルまたはサポートしていない受信チャネルの結果を次の表に示します。
InstanceContextMode 値 | Required | Allowed | NotAllowed |
---|---|---|---|
PerCall | - セッションフル チャネルでの動作 : 呼び出しごとに 1 つのセッションと InstanceContext。 - セッションレス チャネルでの動作: 例外がスローされます。 |
- セッションフル チャネルでの動作 : 呼び出しごとに 1 つのセッションと InstanceContext。 - セッションレス チャネルでの動作 : 呼び出しごとに 1 つの InstanceContext。 |
- セッションフル チャネルでの動作: 例外がスローされます。 - セッションレス チャネルでの動作 : 呼び出しごとに 1 つの InstanceContext。 |
PerSession | - セッションフル チャネルでの動作 : チャネルごとに 1 つのセッションと InstanceContext。 - セッションレス チャネルでの動作: 例外がスローされます。 |
- セッションフル チャネルでの動作 : チャネルごとに 1 つのセッションと InstanceContext。 - セッションレス チャネルでの動作 : 呼び出しごとに 1 つの InstanceContext。 |
- セッションフル チャネルでの動作: 例外がスローされます。 - セッションレス チャネルでの動作 : 呼び出しごとに 1 つの InstanceContext。 |
Single | - セッションフル チャネルでの動作 : すべての呼び出しに対して 1 つのセッションと 1 つの InstanceContext。 - セッションレス チャネルでの動作: 例外がスローされます。 |
- セッションフル チャネルでの動作 : 作成したシングルトンまたはユーザー指定のシングルトンに対して 1 つのセッションと InstanceContext。 - セッションレス チャネルでの動作 : 作成したシングルトンまたはユーザー指定のシングルトンに対して InstanceContext。 |
- セッションフル チャネルでの動作: 例外がスローされます。 - セッションレス チャネルでの動作: 作成したシングルトンまたはユーザー指定のシングルトンごとに InstanceContext。 |