Concurrency

The Concurrency sample demonstrates using the ServiceBehaviorAttribute with the ConcurrencyMode enumeration, which controls whether an instance of a service processes messages sequentially or concurrently. The sample is based on the Getting Started Sample, which implements the ICalculator service contract. This sample defines a new contract, ICalculatorConcurrency, which inherits from ICalculator, providing two additional operations for inspecting the state of the service concurrency. By altering the concurrency setting, you can observe the change in behavior by running the client.

In this sample, the client is a console application (.exe) and the service is hosted by Internet Information Services (IIS).

Note

The setup procedure and build instructions for this sample are located at the end of this topic.

There are three concurrency modes available:

  • Single: Each service instance processes one message at a time. This is the default concurrency mode.

  • Multiple: Each service instance processes multiple messages concurrently. The service implementation must be thread-safe to use this concurrency mode.

  • Reentrant: Each service instance processes one message at a time, but accepts reentrant calls. The service only accepts these calls when it is calling out. Reentrant is demonstrated in the ConcurrencyMode Reentrant sample.

The use of concurrency is related to the instancing mode. In PerCall instancing, concurrency is not relevant, because each message is processed by a new service instance. In Single instancing, either Single or Multiple concurrency is relevant, depending on whether the single instance processes messages sequentially or concurrently. In PerSession instancing, any of the concurrency modes may be relevant.

The service class specifies concurrency behavior with the [ServiceBehavior(ConcurrencyMode=<setting>)] attribute as shown in the code sample that follows. By changing which lines are commented out, you can experiment with the Single and Multiple concurrency modes. Remember to rebuild the service after changing the concurrency mode.

// 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;
    }
}

The sample uses Multiple concurrency with Single instancing by default. The client code has been modified to use an asynchronous proxy. This allows the client to make multiple calls to the service without waiting for a response between each call. You can observe the difference in behavior of the service concurrency mode.

When you run the sample, the operation requests and responses are displayed in the client console window. The concurrency mode that the service is running under is displayed, each operation is called, and then the operation count is displayed. Notice that when the concurrency mode is Multiple, the results are returned in a different order than how they were called, because the service processes multiple messages concurrently. By changing the concurrency mode to Single, the results are returned in the order they were called, because the service processes each message sequentially. Press ENTER in the client window to shut down the client.

To set up, build, and run the sample

  1. Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. If you use Svcutil.exe to generate the proxy client, ensure that you include the /async option.

  3. To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  4. To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

ms752260.Important(en-us,VS.100).gif Note:
The samples may already be installed on your machine. Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WF samples. This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Basic\Services\Behaviors\Concurrency