Reentrant サンプルは、サービス実装で ConcurrencyMode.Reentrant を使用することの必要性と影響を示しています。 ConcurrencyMode.Reentrant は、サービス (またはコールバック) が特定の時点で 1 つのメッセージのみを処理することを意味します ( ConcurencyMode.Single
に似ています)。 スレッド セーフを確保するために、Windows Communication Foundation (WCF) は、メッセージを処理する InstanceContext
をロックして、他のメッセージを処理できないようにします。 再入モードの場合、InstanceContext
はサービスが発信呼び出しを行う直前にロックが解除されるため、後続の呼び出しが次回サービスに入る際にロックを取得できるようになります(サンプルで示されているように、再入可能です)。 この動作を示すために、このサンプルでは、クライアントとサービスが双方向コントラクトを使用して相互にメッセージを送信する方法を示します。
定義されているコントラクトは、サービスによって実装されている Ping
メソッドと、クライアントによって実装されているコールバック メソッド Pong
双方向コントラクトです。 クライアントは、サーバーの Ping
メソッドをティックカウントで呼び出し、それによって呼び出しを開始します。 このサービスは、ティック数が 0 に等しくないかどうかをチェックし、ティック数を減らしながら、メソッド Pong
コールバックを呼び出します。 これは、サンプルの次のコードによって行われます。
public void Ping(int ticks)
{
Console.WriteLine("Ping: Ticks = " + ticks);
//Keep pinging back and forth till Ticks reaches 0.
if (ticks != 0)
{
OperationContext.Current.GetCallbackChannel<IPingPongCallback>().Pong((ticks - 1));
}
}
コールバックの Pong
実装には、 Ping
実装と同じロジックがあります。 つまり、ティック数が 0 ではないかどうかをチェックし、ティック数を 1 減らしてからコールバック チャネルで Ping
メソッドを呼び出します(この場合、元の Ping
メッセージの送信に使用されたチャネルです)。 チック カウントが 0 になると、このメソッドは返されます。これによってすべての応答のラップが解除され、クライアントが呼び出して初期化した最初の呼び出しに戻されます。 これはコールバック実装に示されています。
public void Pong(int ticks)
{
Console.WriteLine("Pong: Ticks = " + ticks);
if (ticks != 0)
{
//Retrieve the Callback Channel (in this case the Channel which was used to send the
//original message) and make an outgoing call until ticks reaches 0.
IPingPong channel = OperationContext.Current.GetCallbackChannel<IPingPong>();
channel.Ping((ticks - 1));
}
}
Ping
メソッドとPong
メソッドはどちらも要求/応答です。つまり、Ping
の最初の呼び出しは、CallbackChannel<T>.Pong()
の呼び出しが返されるまで戻りません。 クライアントでは、 Pong
メソッドは、次の Ping
呼び出しが返されるまで戻ることができません。 コールバックとサービスの両方が保留中の要求に対して応答する前に送信要求/応答呼び出しを行う必要があるため、両方の実装に ConcurrencyMode.Reentrant 動作のマークを付ける必要があります。
サンプルを設定、ビルド、実行するには
Windows Communication Foundation サンプル のOne-Time セットアップ手順を実行していることを確認します。
ソリューションの C# または Visual Basic .NET エディションをビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。
単一または複数のコンピューター間の構成でサンプルを実行するには、「Windows Communication Foundation Samplesの実行」の手順に従います。
対象
サンプルを実行するには、クライアント プロジェクトとサーバー プロジェクトをビルドします。 次に、2 つのコマンド ウィンドウを開き、ディレクトリを <ample>\CS\Service\bin\debug と <sample>\CS\Client\bin\debug ディレクトリに変更します。 次に、「 service.exe
」と入力してサービスを開始し、入力引数として渡されたティックの初期値を使用して Client.exe を呼び出します。 サンプルでは、チックとして 10 が出力されます。
Prompt>Service.exe
ServiceHost Started. Press Enter to terminate service.
Ping: Ticks = 10
Ping: Ticks = 8
Ping: Ticks = 6
Ping: Ticks = 4
Ping: Ticks = 2
Ping: Ticks = 0
Prompt>Client.exe 10
Pong: Ticks = 9
Pong: Ticks = 7
Pong: Ticks = 5
Pong: Ticks = 3
Pong: Ticks = 1