Partager via


ConcurrencyMode Énumération

Définition

Spécifie si une classe de service prend en charge des modes d'opération monothread ou multithread.

public enum class ConcurrencyMode
public enum ConcurrencyMode
type ConcurrencyMode = 
Public Enum ConcurrencyMode
Héritage
ConcurrencyMode

Champs

Multiple 2

L'instance de service est multithread. Il n'existe aucune garantie de synchronisation. Comme d’autres threads peuvent modifier votre objet de service n’importe quand, vous devez gérer à tout moment la synchronisation et la cohérence d’état.

Reentrant 1

L'instance de service est monothread et accepte des appels réentrants. Le service réentrant accepte des appels lorsque vous appelez un autre service ; il vous incombe par conséquent d'assurer la cohérence de l'état de vos objets avant les appels sortants et vous devez confirmer que les données d'opération locales sont valides après des appels sortants. Notez que l’instance de service est déverrouillée uniquement en appelant un autre service sur un canal WCF. Dans ce cas, le service appelé peut réentrer le premier service via un rappel. Si le premier service n'est pas réentrant, la séquence des appels provoque un interblocage. Pour plus d'informations, consultez ConcurrencyMode.

Single 0

L'instance de service est monothread et n'accepte pas d'appels réentrants. Si la propriété InstanceContextMode est Single, et que des messages supplémentaires arrivent pendant que l'instance sert un appel, ces messages doivent attendre jusqu'à ce que le service soit disponible ou jusqu'à expiration de leur délai d'attente.

Exemples

L’exemple de code suivant illustre la différence entre l’utilisation de Single, Reentrant et Multiple. Cet exemple ne se compile pas sans une implémentation réelle derrière elle, mais il illustre le type de garanties de thread que WCF apporte et ce que cela signifie pour votre code d’opération.

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

Remarques

ConcurrencyMode est utilisé conjointement avec la propriété ConcurrencyMode pour spécifier si une classe de service prend en charge des modes d'opération monothread ou multithread. Une opération monothread peut être réentrante ou non réentrante.

Le tableau suivant indique quand Windows Communication Foundation (WCF) autorise l’appel d’une opération pendant qu’une autre opération est en cours, en fonction de .ConcurrencyMode

Valeur ConcurrencyMode Une nouvelle opération peut-elle être appelée ?
Unique Jamais.
Réentrant Uniquement pendant l'appel d'un autre service ou d'un rappel.
Multiple Toujours.

S’applique à