Compartilhar via


ConcurrencyMode Enumeração

Definição

Especifica se uma classe de serviço dá suporte a modos de operação single-thread ou multithread.

public enum class ConcurrencyMode
public enum ConcurrencyMode
type ConcurrencyMode = 
Public Enum ConcurrencyMode
Herança
ConcurrencyMode

Campos

Multiple 2

A instância do serviço é multithread. Nenhuma garantia de sincronização é feita. Como outros threads podem alterar o objeto de serviço a qualquer momento, você deve tratar a sincronização e consistência de estado o tempo todo.

Reentrant 1

A instância de serviço é single-thread e aceita chamadas reentrantes. O serviço reentrante aceita chamadas quando você chama outro serviço, portanto, é sua responsabilidade manter o estado de seu objeto consistente antes dos textos explicativos e você deve confirmar se os dados de local da operação são válidos após os textos explicativos. Observe que a instância do serviço é desbloqueada somente chamando outro serviço em um canal do WCF. Nesse caso, o serviço chamado pode reinserir o primeiro serviço por meio de um retorno de chamada. Se o primeiro serviço não for reentrante, a sequência de chamadas resultará em um deadlock. Para obter detalhes, consulte ConcurrencyMode.

Single 0

A instância do serviço é single-thread e não aceita chamadas reentrantes. Se a propriedade InstanceContextMode for Single e chegarem mensagens adicionais enquanto a instância atende a uma chamada, essas mensagens deverão aguardar até que o serviço esteja disponível ou até as mensagens atingirem o tempo limite.

Exemplos

O exemplo de código a seguir demonstra a diferença entre o uso de Single, Reentrant e Multiple. Este exemplo não é compilado sem uma implementação real por trás dele, mas demonstra o tipo de garantias de threading que o WCF faz e o que isso significa para o código de operação.

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

Comentários

ConcurrencyMode é usado em conjunto com a ConcurrencyMode propriedade para especificar se uma classe de serviço dá suporte a modos de operação de thread único ou de vários threads. Uma operação de thread único pode ser reentrant ou não reentrant.

A tabela a seguir mostra quando Windows Communication Foundation (WCF) permite que uma operação seja invocada enquanto outra estiver em andamento, dependendo do ConcurrencyMode.

Valor ConcurrencyMode Uma nova operação pode ser invocada?
Single Nunca.
Reentrante Somente ao invocar outro serviço ou um retorno de chamada.
Vários Sempre.

Aplica-se a