ServiceBehaviorAttribute.ConcurrencyMode Proprietà

Definizione

Ottiene o imposta un valore che indica se un servizio supporta un solo thread, più thread o chiamate rientranti.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

Valore della proprietà

Uno dei valori di ConcurrencyMode. Il valore predefinito è Single.One of the ConcurrencyMode values; the default is Single.

Eccezioni

Il valore non appartiene all'enumerazione ConcurrencyMode.The value is not one of the ConcurrencyMode values.

Esempi

Nell'esempio di codice seguente vengono illustrate le differenze tra l'utilizzo di Single, Reentrant e Multiple.The following code example demonstrates the different between using Single, Reentrant, and Multiple. Questo esempio non viene compilato senza un'implementazione reale sottostante, ma illustra il tipo di threading garantisce che Windows Communication Foundation (WCF) fa e che cosa significa per il codice operativo.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;
  }
}

Commenti

Questa proprietà indica se un'istanza di un servizio può supportare un solo thread o più thread eseguiti contemporaneamente e, in caso di thread singolo, se è supportata la reentrancy.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.

Nota

La proprietà ConcurrencyMode interagisce con altre impostazioni.The ConcurrencyMode property interacts with some other settings. Ad esempio, se si imposta il valore InstanceContextMode su Single, il servizio può elaborare un solo messaggio alla volta, a meno che il valore di ConcurrencyMode non venga impostato su 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. Questa proprietà genera inoltre un comportamento in combinazione con la proprietà ServiceContractAttribute.SessionMode.This property also produces behavior in combination with the ServiceContractAttribute.SessionMode property. Per informazioni dettagliate, vedere sessioni, istanze e concorrenza.For details, see Sessions, Instancing, and Concurrency.

L'impostazione di ConcurrencyMode su Single indica al sistema di limitare le istanze del servizio a un solo thread di esecuzione alla volta, evitando in questo modo di incorrere in problemi di threading.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. Un valore Multiple indica che gli oggetti servizio possono essere eseguiti da più thread contemporaneamente.A value of Multiple means that service objects can be executed by multiple threads at any one time. In questo caso, è necessario garantire la sicurezza dei thread.In this case, you must ensure thread safety.

Reentrantlimita inoltre l'accesso a un singolo thread alla volta. durante l'elaborazione dell'operazione, nessun altro messaggio può accedere all'operazione.Reentrant also restricts access to a single thread at a time; while the operation is processing, no other message can enter the operation. Se durante l'operazione, viene avviata una chiamata a un'altro servizio, il messaggio corrente perde il blocco sull'operazione che diventa libera di elaborare altri messaggi.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. Quando la chiamata del servizio viene restituita, il blocco viene ristabilito e il messaggio originale può continuare l'elaborazione fino al termine o fino a quando non si verifica un'altra chiamata dell'operazione.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.

Importante

Anche se Single limita le istanze del servizio a un solo thread di esecuzione alla volta, è necessario impostare MaxConcurrentCalls anche su 1 per garantire che non siano presenti messaggi non ordinati.Even 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.

Inoltre, è responsabilità dell'utente mantenere coerente lo stato dell'oggetto prima dei callout ed è necessario confermare che i dati locali dell'operazione siano validi dopo i callout.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. Si noti che l'istanza del servizio viene sbloccata solo chiamando un altro servizio su un canale WCF.Note that the service instance is unlocked only by calling another service over a WCF channel. In questo caso, il servizio chiamato può rientrare nel primo servizio tramite un callback.In this case, the called service can reenter the first service via a callback. Se il primo servizio non è rientrante, la sequenza di chiamate determina un deadlock.If the first service is not reentrant, the sequence of calls results in a deadlock. Per informazioni dettagliate, vedere ConcurrencyMode.For details, see ConcurrencyMode.

Durante qualsiasi chiamata in uscita da un'operazione di elaborazione, è possibile modificare i dati non locali rispetto all'operazioneDuring any outbound call from a processing operation, data not local to the operation can be modified. (la validità dei dati allo stato locale viene garantita alla ripresa dell'elaborazione del messaggio originale). Di conseguenza, prima della chiamata in uscita è necessario verificare che i dati non locali siano validi per le altre chiamate in ingresso e convalidare i dati non locali dopo la restituzione della chiamata in uscita.(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.

Nello pseudo-codice seguente viene illustrato il modello necessario per il supporto delle chiamate rientranti.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;  
}  
  

Se si usa il modello di chiamata asincrona Begin/End per una chiamata in uscita quando la proprietà ConcurrencyMode è Reentrant, viene generata un'eccezione.Using the Begin/End asynchronous call pattern for an outbound call when the ConcurrencyMode is Reentrant triggers an exception. Per le chiamate in uscita asincrone è necessaria un'operazione in cui ConcurrencyMode è Multiple, nel qual caso sarà necessario gestire problemi di sincronizzazione.Asynchronous outbound calls require an operation in which ConcurrencyMode is Multiple, in which case you must handle synchronization issues.

In genere, se arriva un messaggio per un'istanza che viola la modalità di concorrenza, il messaggio resta in attesa fino a quando l'istanza non diventa disponibile o fino al timeout.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.

Inoltre, se ConcurrencyMode è impostata su Single e una chiamata rientrante è bloccata in attesa che l'istanza sia disponibile, il sistema rileva il deadlock e genera un'eccezione.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.

Nota

Viene generata una InvalidOperationException in fase di esecuzione se la proprietà ReleaseServiceInstanceOnTransactionComplete è true quando la proprietà ConcurrencyMode è impostata su Single.A InvalidOperationException is thrown at runtime if ReleaseServiceInstanceOnTransactionComplete is true when the ConcurrencyMode property is set to Single.

Si noti che è necessario impostare in modo esplicito la proprietà ReleaseServiceInstanceOnTransactionComplete su false se è presente un'operazione con la proprietà OperationBehaviorAttribute.TransactionScopeRequired impostata su true e si imposta la proprietà ConcurrencyMode su 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. In caso contrario, viene generata un'eccezione di convalida perché il valore predefinito della proprietà ReleaseServiceInstanceOnTransactionComplete è true.Otherwise a validation exception is thrown because the default value of ReleaseServiceInstanceOnTransactionComplete is true.

Esiste un'interazione fra la proprietà ConcurrencyMode e altre proprietà in grado di modificare il comportamento di runtime.There is an interaction of the ConcurrencyMode and other properties that can alter runtime behavior. Per una descrizione completa di queste interazioni, vedere sessioni, istanze e concorrenza.For a complete description of these interactions, see Sessions, Instancing, and Concurrency.

Si applica a