并发

并发示例演示如何使用ServiceBehaviorAttributeConcurrencyMode枚举,该枚举控制服务实例是按顺序还是并发处理消息。 此示例基于名为Getting Started的指南,并实现ICalculator服务协定。 此示例定义了一个新的协定,ICalculatorConcurrency,该协定继承自ICalculator,并提供两个额外的操作来检查服务并发的状态。 通过更改并发设置,可以通过运行客户端来观察行为更改。

在此示例中,客户端是一个控制台应用程序 (.exe),服务是由 Internet 信息服务 (IIS) 承载的。

注释

本示例的设置过程和生成说明位于本主题末尾。

有三种可用的并发模式:

  • Single:每个服务实例一次处理一条消息。 这是默认并发模式。

  • Multiple:每个服务实例并发处理多个消息。 服务实现必须线程安全才能使用此并发模式。

  • Reentrant:每个服务实例一次处理一个消息,但接受可重入调用。 仅当服务对外调用时才会接受这些调用。重入在 ConcurrencyMode.Reentrant 示例中进行了演示。

并发的使用与实例化模式有关。 在PerCall实例化中,并发性不相关,因为每个消息都由一个新的服务实例处理。 在 Single 实例化过程中,与 SingleMultiple 并发有关,具体取决于单个实例是依次还是同时处理消息。 在PerSession的实例化过程中,任何并发模式都可能是相关的。

服务类使用 [ServiceBehavior(ConcurrencyMode=<setting>)] 属性来指定并发行为,如下面的代码示例所示。 通过更换注释掉的行,您可以体验 SingleMultiple 并发模式。 请记得在更改并发模式后重新生成服务。

// 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 示例 执行One-Time 安装过程。

  2. 如果使用 Svcutil.exe 生成代理客户端,请确保包含该 /async 选项。

  3. 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

  4. 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。