Sdílet prostřednictvím


ServiceBehaviorAttribute.ConcurrencyMode Vlastnost

Definice

Získá nebo nastaví, zda služba podporuje jedno vlákno, více vláken nebo opakované volání.

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

Hodnota vlastnosti

Jedna z ConcurrencyMode hodnot; výchozí hodnota je Single.

Výjimky

Hodnota není jednou z hodnot ConcurrencyMode .

Příklady

Následující příklad kódu ukazuje rozdíl mezi použitím Single, Reentranta Multiple. Tato ukázka není kompilována bez skutečné implementace za ním, ale demonstruje druh záruky podprocesů, které Windows Communication Foundation (WCF) dělá a co to znamená pro váš provozní kód.

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

Poznámky

Tato vlastnost označuje, zda instance služby může zpracovávat jedno vlákno nebo více vláken, které se spouští současně, a pokud je jednovláknové, zda je podporována opětovná zaentrování.

Poznámka

Vlastnost ConcurrencyMode komunikuje s některými dalšími nastaveními. Pokud je například hodnota nastavená na Single výsledek, znamená to, že vaše služba může zpracovat pouze jednu zprávu najednou, InstanceContextMode pokud hodnotu nenastavíte ConcurrencyMode na Multiplehodnotu . Tato vlastnost také vytváří chování v kombinaci s ServiceContractAttribute.SessionMode vlastností . Podrobnosti najdete v tématech Relace, Vytváření instancí a Souběžnost.

Nastavení ConcurrencyMode na dává Single systému pokyn, aby omezil instance služby na jedno vlákno provádění najednou, což vás osvobodí od řešení problémů s podprocesy. Hodnota Multiple znamená, že objekty služby mohou být spuštěny více vlákny najednou. V takovém případě musíte zajistit bezpečnost vláken.

Reentrant omezuje také přístup k jednomu vláknu najednou; zatímco se operace zpracovává, nemůže do operace vstoupit žádná jiná zpráva. Pokud během operace volání jiné služby odejde, aktuální zpráva ztratí zámek operace, což je volné pro zpracování jiných zpráv. Když volání služby vrátí, zámek je znovu vytvořen a původní zpráva může pokračovat ve zpracování až do svého závěru nebo dokud nedojde k jinému volání operace.

Důležité

I když Single omezuje instance služby na jedno vlákno spuštění najednou, musíte také nastavit MaxConcurrentCalls na 1, aby se zajistily žádné zprávy mimo pořadí.

Je také vaší zodpovědností nechat stav objektu konzistentní před popisky a musíte potvrdit, že místní data operace jsou platná po bublinových popiscích. Všimněte si, že instance služby je odemčena pouze voláním jiné služby přes kanál WCF. V tomto případě může volaná služba znovu zadat první službu prostřednictvím zpětného volání. Pokud se první služba znovu nezadá, posloupnost volání způsobí zablokování. Podrobnosti najdete v tématu ConcurrencyMode.

Během jakéhokoli odchozího volání z operace zpracování je možné upravit data, která nejsou místní pro operaci. (Po obnovení původní zprávy je zaručeno, že data místního stavu budou platná.) V důsledku toho musíte před odchozím voláním zajistit, aby jiná než místní data byla platná pro ostatní příchozí volání, a po vrácení odchozího volání znovu ověřit jiná než místní data.

Následující pseudokód znázorňuje požadovaný vzor pro úspěšnou podporu opětovného přihlášení.

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

Použití vzoru zahájení/konce asynchronního volání pro odchozí volání, když ConcurrencyMode is Reentrant aktivuje výjimku. Asynchronní odchozí volání vyžadují operaci , ve které ConcurrencyMode je Multiple. V takovém případě musíte vyřešit problémy se synchronizací.

Obecně platí, že pokud přijde zpráva pro instanci, která porušuje její režim souběžnosti, zpráva počká, dokud instance nebude k dispozici, nebo dokud nevypadne její časový limit.

Kromě toho, pokud ConcurrencyMode je nastavena na Single a opakované volání je blokováno při čekání na uvolnění instance systém zjistí vzájemné zablokování a vyvolá výjimku.

Poznámka

Vyvolá InvalidOperationException se za běhu, pokud ReleaseServiceInstanceOnTransactionComplete je true vlastnost nastavená ConcurrencyMode na Single.

Všimněte si, že pokud je operace nastavená OperationBehaviorAttribute.TransactionScopeRequired na hodnotu true a ConcurrencyMode nastavená na false , musíte explicitně nastavit ReleaseServiceInstanceOnTransactionComplete na Reentranthodnotu . V opačném případě dojde k výjimce ověření, protože výchozí hodnota je ReleaseServiceInstanceOnTransactionCompletetrue.

Existuje interakce ConcurrencyMode vlastností a dalších vlastností, které mohou změnit chování modulu runtime. Úplný popis těchto interakcí najdete v tématu Relace, vytváření instancí a souběžnost.

Platí pro