Freigeben über


ServiceBehaviorAttribute.ConcurrencyMode Eigenschaft

Definition

Ruft ab oder legt fest, ob ein Dienst einen Thread, mehrere Threads oder erneute Aufrufe unterstützt.

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

Eigenschaftswert

Einer der ConcurrencyMode Werte; der Standardwert ist Single.

Ausnahmen

Der Wert ist nicht einer der ConcurrencyMode Werte.

Beispiele

Das folgende Codebeispiel veranschaulicht die unterschiede zwischen der Verwendung von Single, , Reentrantund Multiple. In diesem Beispiel wird nicht ohne eine echte Implementierung dahinter kompiliert, sondern die Art von Threading garantiert, dass Windows Communication Foundation (WCF) erstellt wird und was dies für Den Vorgangscode bedeutet.

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

Hinweise

Diese Eigenschaft gibt an, ob eine Instanz eines Diensts einen Thread oder mehrere Threads verarbeiten kann, die gleichzeitig ausgeführt werden, und ob singlethreaded, ob reentrancy unterstützt wird.

Hinweis

Die ConcurrencyMode Eigenschaft interagiert mit einigen anderen Einstellungen. Wenn der InstanceContextMode Wert beispielsweise auf Single das Ergebnis festgelegt ist, dass Ihr Dienst nur jeweils eine Nachricht verarbeiten kann, es sei denn, Sie legen den ConcurrencyMode Wert auch auf Multiple. Diese Eigenschaft erzeugt auch verhalten in Kombination mit der ServiceContractAttribute.SessionMode Eigenschaft. Ausführliche Informationen finden Sie unter Sitzungen, Instancing und Parallelität.

Die Einstellung ConcurrencyMode weist das System an Single , Instanzen des Diensts gleichzeitig auf einen Ausführungsthread zu beschränken, der Ihnen den Umgang mit Threadingproblemen freigibt. Ein Wert von Multiple bedeutet, dass Dienstobjekte jederzeit von mehreren Threads ausgeführt werden können. In diesem Fall müssen Sie die Threadsicherheit sicherstellen.

Reentrant schränkt auch den Zugriff auf einen einzelnen Thread gleichzeitig ein; Während der Vorgang verarbeitet wird, kann keine andere Nachricht den Vorgang eingeben. Wenn während des Vorgangs ein Aufruf an einen anderen Dienst verlässt, verliert die aktuelle Nachricht die Sperre für den Vorgang, der frei ist, andere Nachrichten zu verarbeiten. Wenn der Dienst den Rückruf zurückgibt, wird die Sperre erneut eingerichtet, und die ursprüngliche Nachricht kann die Verarbeitung fortsetzen, bis ein anderer Aufruf des Vorgangs auftritt.

Von Bedeutung

Single Obwohl Instanzen des Diensts gleichzeitig auf einen Ausführungsthread beschränkt werden, müssen Sie auch auf 1 festlegenMaxConcurrentCalls, um keine Out-of-Order-Nachrichten zu garantieren.

Außerdem liegt es in Ihrer Verantwortung, den Objektzustand vor Beschriftungen konsistent zu lassen, und Sie müssen bestätigen, dass betriebslokale Daten nach Beschriftungen gültig sind. Beachten Sie, dass die Dienstinstanz nur durch Aufrufen eines anderen Diensts über einen WCF-Kanal entsperrt wird. In diesem Fall kann der aufgerufene Dienst den ersten Dienst über einen Rückruf erneut aufrufen. Wenn der erste Dienst nicht erneut ausgeführt wird, führt die Abfolge von Aufrufen zu einem Deadlock. Weitere Informationen finden Sie unter ConcurrencyMode.

Während eines ausgehenden Anrufs aus einem Verarbeitungsvorgang können daten, die nicht lokal für den Vorgang sind, geändert werden. (Lokale Zustandsdaten sind garantiert gültig, wenn die ursprüngliche Nachricht die Verarbeitung fortschreibt.) Daher müssen Sie vor dem ausgehenden Anruf sicherstellen, dass nicht lokale Daten für andere eingehende Anrufe gültig sind und nicht lokale Daten nach rückgabe des ausgehenden Anrufs erneut zurückgegeben werden.

Der folgende Pseudocode veranschaulicht das erforderliche Muster für die erfolgreiche erneute Unterstützung.

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

Verwenden des asynchronen Begin/End-Aufrufmusters für einen ausgehenden Anruf, wenn die ConcurrencyMode Ausnahme ausgelöst wird Reentrant . Für asynchrone ausgehende Aufrufe ist ein Vorgang ConcurrencyModeMultipleerforderlich. In diesem Fall müssen Sie Synchronisierungsprobleme behandeln.

Wenn eine Nachricht in der Regel für eine Instanz eingeht, die gegen den Parallelitätsmodus verstößt, wartet die Nachricht, bis die Instanz verfügbar ist, oder bis das Zeitüberschreitung auftritt.

Wenn die ConcurrencyMode Einstellung auf Single und ein erneuter Aufruf blockiert wird, während die Instanz freigegeben wird, erkennt das System das Deadlock und löst eine Ausnahme aus.

Hinweis

Ein InvalidOperationException Fehler wird zur Laufzeit ausgelöst, wenn ReleaseServiceInstanceOnTransactionComplete die trueConcurrencyMode Eigenschaft auf " Single.

Beachten Sie, dass Sie explizit festlegen falseReleaseServiceInstanceOnTransactionComplete müssen, ob ein Vorgang mit OperationBehaviorAttribute.TransactionScopeRequired dem Wert "true" vorhanden ist und Sie auf ConcurrencyMode "Reentrant. Andernfalls wird eine Gültigkeitsprüfungs ausnahme ausgelöst, da der Standardwert ReleaseServiceInstanceOnTransactionComplete lautet true.

Es gibt eine Interaktion der ConcurrencyMode und anderer Eigenschaften, die das Laufzeitverhalten ändern können. Eine vollständige Beschreibung dieser Interaktionen finden Sie unter Sitzungen, Instancing und Parallelität.

Gilt für: