Compartir vía


ServiceBehaviorAttribute.ConcurrencyMode Propiedad

Definición

Obtiene o establece si un servicio admite un subproceso, varios subprocesos o llamadas reentrantes.

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

Valor de propiedad

ConcurrencyMode

Uno de los valores de ConcurrencyMode; el valor predeterminado es Single.

Excepciones

El valor no es uno de los valores de ConcurrencyMode.

Ejemplos

El siguiente ejemplo de código muestra la diferencia de uso entre Single, Reentrant y Multiple. Este ejemplo no se compila sin una implementación real detrás de él, pero demuestra el tipo de subproceso garantiza que Windows Communication Foundation (WCF) realiza y qué significa para el código de operación.

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

Comentarios

Esta propiedad indica si una instancia de un servicio puede administrar un subproceso o varios subprocesos que se ejecutan de forma simultánea y, si es de un único subproceso, si se admite la reentrada.

Nota

La propiedad ConcurrencyMode interactúa con algunos otros valores. Por ejemplo, si el valor InstanceContextMode está establecido como Single, el resultado será que su servicio sólo puede procesar un mensaje a la vez a menos que también establezca el valor de ConcurrencyMode como Multiple. Esta propiedad también genera comportamiento en combinación con la propiedad ServiceContractAttribute.SessionMode. Para más información, consulte Sesiones, Creación de instancias y Simultaneidad.

Al establecer ConcurrencyMode como Single se le indica al sistema que restrinja las instancias del servicio a un subproceso de ejecución de cada vez, lo que lo libera de problemas con los subprocesos. Un valor de Multiple indica que varios subprocesos pueden ejecutar los objetos de servicio en cualquier momento. En este caso, debe garantizar la seguridad para subprocesos.

Reentrant también restringe el acceso a un único subproceso a la vez; mientras la operación se está procesando, ningún otro mensaje puede escribir la operación. Si durante la operación se va una llamada a otro servicio, el mensaje actual pierde el bloqueo en la operación, que es libre de procesar otros mensajes. Cuando la llamada del servicio regresa, se restablece el bloqueo y el mensaje original puede seguir procesándose hasta su conclusión o hasta que se produzca otra llamada fuera de la operación.

Importante

Single Aunque restringe las instancias del servicio a un subproceso de ejecución a la vez, también debe establecer en MaxConcurrentCalls 1 para garantizar que no haya mensajes desordenados.

Además, es su responsabilidad dejar el estado del objeto coherente antes de las llamadas y debe confirmar que los datos locales de la operación son válidos después de las llamadas. Tenga en cuenta que la instancia del servicio solo se desbloquea llamando a otro servicio a través de un canal de WCF. En este caso, el servicio al que se ha llamado puede reentrar al primer servicio mediante una devolución de llamada. Si el primer servicio no es reentrante, la secuencia de llamadas resulta en un interbloqueo. Para obtener información detallada, vea ConcurrencyMode.

Durante cualquier llamada saliente de una operación del procesamiento, se pueden modificar los datos que no son locales de la operación. (Se garantiza que los datos de estado local son válidos cuando el mensaje original reanuda el procesamiento). Como resultado, antes de la llamada saliente, debe asegurarse de que los datos no locales son válidos para otras llamadas entrantes y volver a validar los datos no locales después de que se devuelva la llamada saliente.

El pseudocódigo siguiente muestra el modelo necesario para la compatibilidad reentrante correcta.

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

Al utilizar el modelo de llamada asincrónica Begin/End para una llamada saliente cuando ConcurrencyMode es Reentrant se inicia una excepción. Las llamadas salientes asincrónicas requieren una operación en la que ConcurrencyMode es Multiple. En ese caso deberá administrar los problemas de sincronización.

Generalmente, si llega un mensaje para una instancia que infringe su modo de simultaneidad, el mensaje espera hasta que la instancia esté disponible, o hasta que expire.

Además, si ConcurrencyMode está establecido como Single y se bloquea una llamada reentrante esperando a que la instancia se libere, el sistema detecta el interbloqueo e inicia una excepción.

Nota

Se inicia una InvalidOperationException en tiempo de ejecución si ReleaseServiceInstanceOnTransactionComplete es true cuando la propiedad ConcurrencyMode está establecida como Single.

Tenga en cuenta que debe establecer explícitamente ReleaseServiceInstanceOnTransactionComplete como false si hay una operación con OperationBehaviorAttribute.TransactionScopeRequired establecido como true y usted establece ConcurrencyMode como Reentrant. De lo contrario se producirá una excepción de validación porque el valor predeterminado de ReleaseServiceInstanceOnTransactionComplete es true.

Hay una interacción de ConcurrencyMode y otras propiedades que puede modificar el comportamiento en tiempo de ejecución. Para obtener una descripción completa de estas interacciones, consulte Sesiones, Instancias y Simultaneidad.

Se aplica a