コンカレンシー

コンカレンシーのサンプルでは、ServiceBehaviorAttributeConcurrencyMode 列挙体と共に使用する方法を示します。この列挙体により、サービスのインスタンスがメッセージを順序に従って処理するか、または同時に処理するかが制御されます。 このサンプルは、ICalculator サービス コントラクトを実装する「入門サンプル」に基づいています。 このサンプルでは、ICalculatorConcurrency から継承される新しいコントラクト ICalculator を定義します。これによって、サービスのコンカレンシーの状態を検査するための 2 つの操作が追加されます。 コンカレンシー設定を変更してから、クライアントを実行して動作の変更を確認します。

この例では、クライアントはコンソール アプリケーション (.exe) であり、サービスはインターネット インフォメーション サービス (IIS) によってホストされます。

Note

このサンプルのセットアップ手順とビルド手順については、このトピックの最後を参照してください。

選択可能なコンカレンシー モードは次の 3 つです。

  • Single: 各サービス インスタンスは、一度に 1 つのメッセージを処理します。 これが既定のコンカレンシー モードです。

  • Multiple: 各サービス インスタンスは、同時に複数のメッセージを処理します。 このコンカレンシー モードを使用するには、サービスの実装がスレッドセーフである必要があります。

  • Reentrant: 各サービス インスタンスは、一度に 1 つのメッセージを処理しますが、再入可能呼び出しを受け入れます。 サービスでは、それ自体が呼び出し元である場合にのみ、これらの呼び出しを受け入れます。再入は、「ConcurrencyMode.Reentrant」のサンプルで示されています。

コンカレンシーの使用は、インスタンス化モードに関連します。 ph x="1" /> インスタンス化では、各メッセージが新しいサービス インスタンスによって処理されるため、コンカレンシーは関係しません。 ph x="1" /> インスタンス化では、SingleMultiple のいずれかのコンカレンシーが関係します。これは 1 つのインスタンスがメッセージを順番に処理するか、同時に処理するかによって決まります。 ph x="1" /> インスタンス化では、どのコンカレンシー モードも関係する可能性があります。

サービス クラスは、[ServiceBehavior(ConcurrencyMode=<setting>)] 属性を使用してコンカレンシー動作を指定します。次のサンプル コードを参照してください。 行のコメント化を変更して、Single および Multiple のコンカレンシー モードをそれぞれ試してみてください。 コンカレンシー モードを変更したら、サービスを再ビルドする必要があります。

// Single allows a single message to be processed sequentially by each service instance.
//[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]

// Multiple allows concurrent processing of multiple messages by a service instance.
// The service implementation should be thread-safe. This can be used to increase throughput.
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]

// Uses Thread.Sleep to vary the execution time of each operation.
public class CalculatorService : ICalculatorConcurrency
{
    int operationCount;

    public double Add(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(180);
        return n1 + n2;
    }

    public double Subtract(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(100);
        return n1 - n2;
    }

    public double Multiply(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(150);
        return n1 * n2;
    }

    public double Divide(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(120);
        return n1 / n2;
    }

    public string GetConcurrencyMode()
    {
        // Return the ConcurrencyMode of the service.
        ServiceHost host = (ServiceHost)OperationContext.Current.Host;
        ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
        return behavior.ConcurrencyMode.ToString();
    }

    public int GetOperationCount()
    {
        // Return the number of operations.
        return operationCount;
    }
}

サンプルの既定の設定では、Multiple インスタンス化と Single コンカレンシーが使用されます。 クライアント コードは、非同期プロキシを使用するように変更されています。 これにより、クライアントはサービスを呼び出した後に、応答を待たずに次の呼び出しを行うことができます。 サービスのコンカレンシー モードの動作の違いを観察してください。

このサンプルを実行すると、操作要求および応答がクライアントのコンソール ウィンドウに表示されます。 実行中のサービスのコンカレンシー モードが表示され、各操作が呼び出され、その後で操作数が表示されます。 コンカレンシー モードが Multiple の場合、結果が返される順序は呼び出された順序とは異なります。サービスは複数のメッセージを同時に実行するからです。 コンカレンシー モードを Single に変更すると、結果は呼び出された順序どおりに返されます。サービスは各メッセージを順次処理するからです。 クライアントをシャットダウンするには、クライアント ウィンドウで Enter キーを押します。

サンプルをセットアップ、ビルド、および実行するには

  1. Windows Communication Foundation サンプルの 1 回限りのセットアップの手順を実行したことを確認します。

  2. Svcutil.exe を使用してプロキシ クライアントを生成する場合は、/async オプションを指定します。

  3. ソリューションの C# 版または Visual Basic .NET 版をビルドするには、「 Building the Windows Communication Foundation Samples」の手順に従います。

  4. 単一または複数コンピューター構成でサンプルを実行するには、「Windows Communication Foundation サンプルの実行」の手順に従います。