ServiceBehaviorAttribute.ConcurrencyMode 属性

定义

获取或设置一个值,该值指示服务是支持单线程、多线程还是支持可重入调用。Gets or sets whether a service supports one thread, multiple threads, or reentrant calls.

public:
 property System::ServiceModel::ConcurrencyMode ConcurrencyMode { System::ServiceModel::ConcurrencyMode get(); void set(System::ServiceModel::ConcurrencyMode value); };
public System.ServiceModel.ConcurrencyMode ConcurrencyMode { get; set; }
member this.ConcurrencyMode : System.ServiceModel.ConcurrencyMode with get, set
Public Property ConcurrencyMode As ConcurrencyMode

属性值

ConcurrencyMode 值之一,默认值为 SingleOne of the ConcurrencyMode values; the default is Single.

异常

该值不是 ConcurrencyMode 值之一。The value is not one of the ConcurrencyMode values.

示例

下面的代码示例演示使用 SingleReentrantMultiple 之间的区别。The following code example demonstrates the different between using Single, Reentrant, and Multiple. 此示例在未进行实际实现的情况下进行编译不会进行编译, 但会演示 Windows Communication Foundation (WCF) 进行的线程保证种类, 以及这对操作代码的意义。This sample does not compile without a real implementation behind it, but does demonstrate the kind of threading guarantees that Windows Communication Foundation (WCF) makes and what that means for your operation code.

using System;
using System.ServiceModel;

[ServiceContract]
public interface IHttpFetcher
{
  [OperationContract]
  string GetWebPage(string address);
}

// These classes have the invariant that:
//     this.slow.GetWebPage(this.cachedAddress) == this.cachedWebPage.
// When you read cached values you can assume they are valid. When
// you write the cached values, you must guarantee that they are valid.
// With ConcurrencyMode.Single, WCF does not call again into the object
// so long as the method is running. After the operation returns the object
// can be called again, so you must make sure state is consistent before
// returning.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
class SingleCachingHttpFetcher : IHttpFetcher
{
    string cachedWebPage;
    string cachedAddress;
    readonly IHttpFetcher slow;

    public string GetWebPage(string address)
    {
        // <-- Can assume cache is valid.
        if (this.cachedAddress == address)
        {
            return this.cachedWebPage;
        }

        // <-- Cache is no longer valid because we are changing
        // one of the values.
        this.cachedAddress = address;
        string webPage = slow.GetWebPage(address);
        this.cachedWebPage = webPage;
        // <-- Cache is valid again here.

        return this.cachedWebPage;
        // <-- Must guarantee that the cache is valid because we are returning.
    }
}

// With ConcurrencyMode.Reentrant, WCF makes sure that only one
// thread runs in your code at a time. However, when you call out on a
// channel, the operation can get called again on another thread. Therefore 
// you must confirm that state is consistent both before channel calls and
// before you return.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class ReentrantCachingHttpFetcher : IHttpFetcher
{
  string cachedWebPage;
  string cachedAddress;
  readonly SlowHttpFetcher slow;

  public ReentrantCachingHttpFetcher()
  {
    this.slow = new SlowHttpFetcher();
  }

  public string GetWebPage(string address)
  {
    // <-- Can assume that cache is valid.
    if (this.cachedAddress == address)
    {
        return this.cachedWebPage;
    }

    // <-- Must guarantee that the cache is valid, because 
    // the operation can be called again before we return.
    string webPage = slow.GetWebPage(address);
    // <-- Can assume cache is valid.

    // <-- Cache is no longer valid because we are changing
    // one of the values.
    this.cachedAddress = address;
    this.cachedWebPage = webPage;
    // <-- Cache is valid again here.

    return this.cachedWebPage;
    // <-- Must guarantee that cache is valid because we are returning.
  }
}

// With ConcurrencyMode.Multiple, threads can call an operation at any time.  
// It is your responsibility to guard your state with locks. If
// you always guarantee you leave state consistent when you leave
// the lock, you can assume it is valid when you enter the lock.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MultipleCachingHttpFetcher : IHttpFetcher
{
  string cachedWebPage;
  string cachedAddress;
  readonly SlowHttpFetcher slow;
  readonly object ThisLock = new object();

  public MultipleCachingHttpFetcher()
  {
    this.slow = new SlowHttpFetcher();
  }

  public string GetWebPage(string address)
  {
    lock (this.ThisLock)
    {
      // <-- Can assume cache is valid.
      if (this.cachedAddress == address)
      {
          return this.cachedWebPage;
          // <-- Must guarantee that cache is valid because 
          // the operation returns and releases the lock.
      }
      // <-- Must guarantee that cache is valid here because
      // the operation releases the lock.
    }

    string webPage = slow.GetWebPage(address);

    lock (this.ThisLock)
    {
      // <-- Can assume cache is valid.

      // <-- Cache is no longer valid because the operation 
      // changes one of the values.
      this.cachedAddress = address;
      this.cachedWebPage = webPage;
      // <-- Cache is valid again here.

      // <-- Must guarantee that cache is valid because
      // the operation releases the lock.
    }

    return webPage;
  }
}

注解

此属性指示服务实例是可以处理单线程,还是可以同时执行多线程;如果是单线程,是否支持可重入。This property indicates whether an instance of a service can handle one thread or multiple threads that execute concurrently, and if single-threaded, whether reentrancy is supported.

备注

ConcurrencyMode 属性可与其他一些设置进行交互。The ConcurrencyMode property interacts with some other settings. 例如,如果 InstanceContextMode 值设置为 Single,那么结果是您的服务一次只能处理一条消息,除非您还将 ConcurrencyMode 值设置为 MultipleFor example, if the InstanceContextMode value is set to Single the result is that your service can only process one message at a time unless you also set the ConcurrencyMode value to Multiple. 此属性与 ServiceContractAttribute.SessionMode 属性结合时也可生成行为。This property also produces behavior in combination with the ServiceContractAttribute.SessionMode property. 有关详细信息, 请参阅会话、实例化和并发For details, see Sessions, Instancing, and Concurrency.

ConcurrencyMode 设置为 Single,可以指示系统将服务实例限制为一次只运行一个执行线程,如此一来,您就不必处理线程问题。Setting ConcurrencyMode to Single instructs the system to restrict instances of the service to one thread of execution at a time, which frees you from dealing with threading issues. 如果值为 Multiple,则意味着在任一时刻都可以通过多个线程来执行服务对象。A value of Multiple means that service objects can be executed by multiple threads at any one time. 在此情况下,必须确保线程安全。In this case, you must ensure thread safety.

Reentrant还会限制对单个线程的访问一次。在处理操作时, 任何其他消息都不能输入操作。Reentrant also restricts access to a single thread at a time; while the operation is processing, no other message can enter the operation. 如果在操作期间,放弃了对其他服务的调用,则当前消息将释放对该操作的锁定,这时将允许该操作处理其他消息。If during the operation a call to another service leaves, the current message loses the lock on the operation, which is free to process other messages. 如果对该服务的调出重新返回,则会重新建立锁定,并且会继续处理原始消息直到结束,或者直到操作又进行其他调用为止。When the service call out returns, the lock is reestablished and the original message can continue processing to its conclusion or until another call out of the operation occurs.

重要

即使将服务实例MaxConcurrentCalls 限制为一次执行一个线程,还必须将设置为1以保证无序消息。SingleEven though Single restricts instances of the service to one thread of execution at a time, you must also set MaxConcurrentCalls to 1 to guarantee no out-of-order messages.

此外, 您还需要在标注之前保持对象状态一致, 并且必须确认操作本地数据在标注后有效。Also, it is your responsibility to leave your object state consistent before callouts and you must confirm that operation-local data is valid after callouts. 请注意,只有通过 WCF 通道调用其他服务,才能解锁服务实例。Note that the service instance is unlocked only by calling another service over a WCF channel. 在此情况下,已调用的服务可以通过回调重入第一个服务。In this case, the called service can reenter the first service via a callback. 如果第一个服务不可重入,则该调用顺序会导致死锁。If the first service is not reentrant, the sequence of calls results in a deadlock. 有关详细信息,请参阅 ConcurrencyModeFor details, see ConcurrencyMode.

处理操作进行任何出站调用期间,可以修改对该操作而言非本地的数据。During any outbound call from a processing operation, data not local to the operation can be modified. (原始消息继续处理时,本地状态的数据一定有效。)所以,在出站调用前,必须确保非本地数据对于其他传入调用有效,并在出站调用返回后重新验证非本地数据。(Local state data is guaranteed to be valid when the original message resumes processing.) As a result, before your outbound call you must ensure that non-local data is valid for other incoming calls and revalidate non-local data after the outbound call returns.

下面的伪代码演示要获得成功可重入支持必须使用的模式。The following pseudo-code illustrates the required pattern for successful reentrant support.

public void MyMethod()  
{  
  this.SomeNonLocalDataState;  
  // Here you need to clean nonlocal state for other users  
  OutboundProxy proxy = new OutboundProxy();  
  int returnValue = proxy.CallOutOfOperation();  
  // Ensure that this.SomeNonLocalDataState is valid for continued use.  
  this.ModifyNonLocalState;  
  return returnValue;  
}  
  

ConcurrencyModeReentrant 时,对出站调用使用 Begin/End 异步调用模式会触发异常。Using the Begin/End asynchronous call pattern for an outbound call when the ConcurrencyMode is Reentrant triggers an exception. 在异步出站调用所需进行的操作中,ConcurrencyModeMultiple,而在此情况下,必须处理同步问题。Asynchronous outbound calls require an operation in which ConcurrencyMode is Multiple, in which case you must handle synchronization issues.

通常,如果到达的消息与实例的并发模式冲突,则该消息会等待,直到可使用实例或超时为止。Generally, if a message arrives for an instance that violates its concurrency mode, the message waits until the instance is available, or until it times out.

此外,如果 ConcurrencyMode 设置为 Single 且可重入调用已在等待释放实例时被阻止,则系统会检测到死锁,并引发异常。In addition, if the ConcurrencyMode is set to Single and a reentrant call is blocked while waiting for the instance to be freed, the system detects the deadlock and throws an exception.

备注

InvalidOperationException 属性设置为 ReleaseServiceInstanceOnTransactionComplete 时,如果 trueConcurrencyMode,则在运行时会引发 SingleA InvalidOperationException is thrown at runtime if ReleaseServiceInstanceOnTransactionComplete is true when the ConcurrencyMode property is set to Single.

请注意,如果有操作的 ReleaseServiceInstanceOnTransactionComplete 设置为 True,并且您将 false 设置为 OperationBehaviorAttribute.TransactionScopeRequired,请务必将 ConcurrencyMode 显式设置为 ReentrantNote that you must explicitly set ReleaseServiceInstanceOnTransactionComplete to false if there is an operation with OperationBehaviorAttribute.TransactionScopeRequired set to true and you set ConcurrencyMode to Reentrant. 否则,由于 ReleaseServiceInstanceOnTransactionComplete 的默认值为 true,因此将引发验证异常。Otherwise a validation exception is thrown because the default value of ReleaseServiceInstanceOnTransactionComplete is true.

ConcurrencyMode 和其他属性之间的交互可能会更改运行时行为。There is an interaction of the ConcurrencyMode and other properties that can alter runtime behavior. 有关这些交互的完整说明, 请参阅会话、实例化和并发For a complete description of these interactions, see Sessions, Instancing, and Concurrency.

适用于