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; значение по умолчанию — Single.One of the ConcurrencyMode values; the default is Single.

Исключения

Данное значение не является одним из значений ConcurrencyMode.The value is not one of the ConcurrencyMode values.

Примеры

В следующем примере кода показано различие между использованием значений Single, Reentrant и Multiple.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 также не будет задано как Multiple.For 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. Дополнительные сведения см. в разделе ConcurrencyMode.For 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;  
}  
  

С помощью шаблона асинхронных вызовов Begin/End для исходящего вызова, когда ConcurrencyMode является Reentrant, выдается исключение.Using the Begin/End asynchronous call pattern for an outbound call when the ConcurrencyMode is Reentrant triggers an exception. Для асинхронных исходящих вызовов требуется операция, при которой ConcurrencyMode является Multiple, и в этом случае следует обработать проблемы синхронизации.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 является true, когда свойство ConcurrencyMode задано как Single.A InvalidOperationException is thrown at runtime if ReleaseServiceInstanceOnTransactionComplete is true when the ConcurrencyMode property is set to Single.

Обратите внимание, что необходимо явно задать ReleaseServiceInstanceOnTransactionComplete false, если имеется операция с OperationBehaviorAttribute.TransactionScopeRequired, заданным как true, и задается ConcurrencyMode как Reentrant.Note 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. В противном случае будет выдано исключение проверки, поскольку значение по умолчанию ReleaseServiceInstanceOnTransactionCompletetrue.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.

Применяется к