サンプルではなく状態管理に関するメモです。

1.状態管理について

WCFサービスクラスはデフォルトではクライアントとのセッションが維持されます。つまり、クライアントの接続があると、対応する1つのサービスクラスのインスタンスが作成されます。つまり1000クライアントから同時接続されると、1000ものインスタンスが作成されます。これはサービスクラスに付与するServiceBehavor.InstanceContextMode のデフォルト値がInstanceContextMode.PerSessionとなっているためです。InstanceContextModeの種類は次のとおり

PerSession ServiceBehaviorのデフォルト値.各セッション(クライアントから接続があるたび)に、新しくインスタンスが作成されます。OperationBehavior.ReleaseInstanceModeを指定しない限り、クライアントのプロキシを閉じると、インスタンスが破棄されます。
PerCall クライアントがサービスメソッドを呼び出すたびに、新しくインスタンスが作成されます。このモードではセッションごとにインスタンスが作成されないので、スケーラビリティが改善されます。ただし、状態を維持する必要がある場合は、独自で状態管理の方法を実装する必要があります。
Single サービスクラスの1つのインスタンスのみ作成されます。複数のクライアントが接続しても、サービスクラスのインスタンスは1つのみとなります。このインスタンスはWCFのホストプログラムが停止したときのみ破棄されます。

 

以下のようにサービスクラスのServiceBehaviorAttributeで指定します。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class ProductService : IProductService
{....}

ServiceBehavior.InstanceContextModeをInstanceContextMode.Singleとすると、同時に複数のクライアントがサービスメソッドを呼び出しても同時に1つの要求のみが処理されます。そのため、多くのクライアントからリクエストを受けるとタイムアウトが大量に発生する可能性があります。これを避ける場合のひとつの方法として、ServiceBehavior.ConcurrencyModeをSingle(デフォルト)からMultipleにすることで、複数のリクエストを同時に処理できるようになります。ただし、スレッドセーフではなくなるので、同期が必要な処理はサービスクラスの定義者が実装する必要があります。ServiceConcurrencyMode.Reentrantはサービスクラス自身はシングルスレッドで実行されますが、サービスクラス内で別のサービスを呼び出し、呼び出し先の別サービスからコールバックメソッドを呼び出すことができるようにするモードです。

2.サービスクラスのインスタンスの生存期間をコントロールする

OperationBehavior.ReleaseInstanceModeにReleaseInstanceMode.None以外の値を設定することで、インスタンスの生存期間をコントロールできます。ServiceBehavior.ContextModeがPerSessionのときに組み合わせて使用すると効果があります。

AfterCall サービスメソッド呼び出し後にインスタンスを破棄する。
BeforeCall サービスメソッド呼び出し前に既存のインスタンスを破棄し、新しいインスタンスを作成する。
BeforeAndAfterCall サービスメソッド呼び出し前に新しいインスタンスを作成し、呼び出し後にインスタンスを破棄する。
None デフォルトの値。インスタンスの破棄はServiceBehavior.InstanceContextModeにより決定される。

 

3.おまけサービスメソッドの呼び出し順を強制する

ServiceContract.SessionMode, OperationContract.IsInitiating, OperationContract.IsTerminatingを使用して、サービスメソッドの呼び出し順(開始、途中、最後)を強制できるようになります。上述のプロパティはWCFに特化した処理であり、WCF以外のクライアントとの互換性に影響が発生します。詳細内容はMSDNを参照して下さい。