SemaphoreSlim Class

Definition

Representa una alternativa ligera a Semaphore que limita el número de subprocesos que puede obtener acceso a la vez a un recurso o a un grupo de recursos.Represents a lightweight alternative to Semaphore that limits the number of threads that can access a resource or pool of resources concurrently.

public ref class SemaphoreSlim : IDisposable
public class SemaphoreSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class SemaphoreSlim : IDisposable
type SemaphoreSlim = class
    interface IDisposable
Public Class SemaphoreSlim
Implements IDisposable
Inheritance
SemaphoreSlim
Attributes
Implements

Examples

En el ejemplo siguiente se crea un semáforo con un recuento máximo de tres subprocesos y un recuento inicial de cero.The following example creates a semaphore with a maximum count of three threads and an initial count of zero threads. En el ejemplo se inician cinco tareas, todas las cuales bloquean la espera del semáforo.The example starts five tasks, all of which block waiting for the semaphore. El subproceso principal llama a la sobrecarga Release(Int32) para aumentar el recuento del semáforo a su máximo, lo que permite que tres tareas entren en el semáforo.The main thread calls the Release(Int32) overload to increase the semaphore count to its maximum, which allows three tasks to enter the semaphore. Cada vez que se libera el semáforo, se muestra el recuento de semáforos anterior.Each time the semaphore is released, the previous semaphore count is displayed. Seguimiento de mensajes de la consola use.Console messages track semaphore use. El intervalo de trabajo simulado aumenta ligeramente en cada subproceso para que la salida sea más fácil de leer.The simulated work interval is increased slightly for each thread to make the output easier to read.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
    private static SemaphoreSlim semaphore;
    // A padding interval to make the output more orderly.
    private static int padding;

    public static void Main()
    {
        // Create the semaphore.
        semaphore = new SemaphoreSlim(0, 3);
        Console.WriteLine("{0} tasks can enter the semaphore.",
                          semaphore.CurrentCount);
        Task[] tasks = new Task[5];

        // Create and start five numbered tasks.
        for (int i = 0; i <= 4; i++)
        {
            tasks[i] = Task.Run(() =>
            {
                // Each task begins by requesting the semaphore.
                Console.WriteLine("Task {0} begins and waits for the semaphore.",
                                  Task.CurrentId);
                semaphore.Wait();

                Interlocked.Add(ref padding, 100);

                Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId);

                // The task just sleeps for 1+ seconds.
                Thread.Sleep(1000 + padding);

                Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.",
                                  Task.CurrentId, semaphore.Release());
            });
        }

        // Wait for half a second, to allow all the tasks to start and block.
        Thread.Sleep(500);

        // Restore the semaphore count to its maximum value.
        Console.Write("Main thread calls Release(3) --> ");
        semaphore.Release(3);
        Console.WriteLine("{0} tasks can enter the semaphore.",
                          semaphore.CurrentCount);
        // Main thread waits for the tasks to complete.
        Task.WaitAll(tasks);

        Console.WriteLine("Main thread exits.");
    }
}
// The example displays output like the following:
//       0 tasks can enter the semaphore.
//       Task 1 begins and waits for the semaphore.
//       Task 5 begins and waits for the semaphore.
//       Task 2 begins and waits for the semaphore.
//       Task 4 begins and waits for the semaphore.
//       Task 3 begins and waits for the semaphore.
//       Main thread calls Release(3) --> 3 tasks can enter the semaphore.
//       Task 4 enters the semaphore.
//       Task 1 enters the semaphore.
//       Task 3 enters the semaphore.
//       Task 4 releases the semaphore; previous count: 0.
//       Task 2 enters the semaphore.
//       Task 1 releases the semaphore; previous count: 0.
//       Task 3 releases the semaphore; previous count: 0.
//       Task 5 enters the semaphore.
//       Task 2 releases the semaphore; previous count: 1.
//       Task 5 releases the semaphore; previous count: 2.
//       Main thread exits.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Private semaphore As SemaphoreSlim
    ' A padding interval to make the output more orderly.
    Private padding As Integer

   Public Sub Main()
      ' Create the semaphore.
      semaphore = New SemaphoreSlim(0, 3)
      Console.WriteLine("{0} tasks can enter the semaphore.",
                        semaphore.CurrentCount)
      Dim tasks(4) As Task

      ' Create and start five numbered tasks.
      For i As Integer = 0 To 4
         tasks(i) = Task.Run(
            Sub()
               ' Each task begins by requesting the semaphore.
               Console.WriteLine("Task {0} begins and waits for the semaphore.",
                              Task.CurrentId)
               semaphore.Wait()

               Interlocked.Add(padding, 100)

               Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId)

               ' The task just sleeps for 1+ seconds.
               Thread.Sleep(1000 + padding)

               Console.WriteLine("Task {0} releases the semaphore previous count: {1}.",
                                 Task.CurrentId, semaphore.Release())
            End Sub )
      Next

      ' Wait for half a second, to allow all the tasks to start and block.
      Thread.Sleep(500)

      ' Restore the semaphore count to its maximum value.
      Console.Write("Main thread calls Release(3) --> ")
      semaphore.Release(3)
      Console.WriteLine("{0} tasks can enter the semaphore.",
                        semaphore.CurrentCount)
      ' Main thread waits for the tasks to complete.
      Task.WaitAll(tasks)

      Console.WriteLine("Main thread exits.")
   End Sub
End Module
' The example displays output like the following:
'       0 tasks can enter the semaphore.
'       Task 1 begins and waits for the semaphore.
'       Task 5 begins and waits for the semaphore.
'       Task 2 begins and waits for the semaphore.
'       Task 4 begins and waits for the semaphore.
'       Task 3 begins and waits for the semaphore.
'       Main thread calls Release(3) --> 3 tasks can enter the semaphore.
'       Task 4 enters the semaphore.
'       Task 1 enters the semaphore.
'       Task 3 enters the semaphore.
'       Task 4 releases the semaphore; previous count: 0.
'       Task 2 enters the semaphore.
'       Task 1 releases the semaphore; previous count: 0.
'       Task 3 releases the semaphore; previous count: 0.
'       Task 5 enters the semaphore.
'       Task 2 releases the semaphore; previous count: 1.
'       Task 5 releases the semaphore; previous count: 2.
'       Main thread exits.

Remarks

Los semáforos son de dos tipos: semáforos locales y semáforos de sistema con nombre.Semaphores are of two types: local semaphores and named system semaphores. Los semáforos locales son locales para una aplicación, los semáforos del sistema están visibles en todo el sistema operativo y son adecuados para la sincronización entre procesos.Local semaphores are local to an application, system semaphores are visible throughout the operating system and are suitable for inter-process synchronization. El SemaphoreSlim es una alternativa ligera a la clase Semaphore que no utiliza los semáforos del kernel de Windows.The SemaphoreSlim is a lightweight alternative to the Semaphore class that doesn't use Windows kernel semaphores. A diferencia de la clase Semaphore, la clase SemaphoreSlim no admite semáforos de sistema con nombre.Unlike the Semaphore class, the SemaphoreSlim class doesn't support named system semaphores. Solo se puede usar como semáforo local.You can use it as a local semaphore only. La clase SemaphoreSlim es el semáforo recomendado para la sincronización dentro de una sola aplicación.The SemaphoreSlim class is the recommended semaphore for synchronization within a single app.

Un semáforo ligero controla el acceso a un grupo de recursos que es local para la aplicación.A lightweight semaphore controls access to a pool of resources that is local to your application. Al crear una instancia de un semáforo, puede especificar el número máximo de subprocesos que pueden entrar en el semáforo simultáneamente.When you instantiate a semaphore, you can specify the maximum number of threads that can enter the semaphore concurrently. También se especifica el número inicial de subprocesos que pueden entrar en el semáforo simultáneamente.You also specify the initial number of threads that can enter the semaphore concurrently. Esto define el recuento del semáforo.This defines the semaphore's count.

El recuento se reduce cada vez que un subproceso entra en el semáforo y se incrementa cada vez que un subproceso libera el semáforo.The count is decremented each time a thread enters the semaphore, and incremented each time a thread releases the semaphore. Para entrar en el semáforo, un subproceso llama a una de las sobrecargas Wait o WaitAsync.To enter the semaphore, a thread calls one of the Wait or WaitAsync overloads. Para liberar el semáforo, llama a una de las sobrecargas de Release.To release the semaphore, it calls one of the Release overloads. Cuando el número llega a cero, las llamadas subsiguientes a uno de los métodos de Wait se bloquean hasta que otros subprocesos liberan el semáforo.When the count reaches zero, subsequent calls to one of the Wait methods block until other threads release the semaphore. Si se bloquean varios subprocesos, no hay ningún orden garantizado, como FIFO o LIFO, que controla cuándo los subprocesos entran en el semáforo.If multiple threads are blocked, there is no guaranteed order, such as FIFO or LIFO, that controls when threads enter the semaphore.

La estructura básica del código que utiliza un semáforo para proteger los recursos es:The basic structure for code that uses a semaphore to protect resources is:

  
' Enter semaphore by calling one of the Wait or WaitAsync methods.  
SemaphoreSlim.Wait()  
'   
' Execute code protected by the semaphore.   
'  
SemaphoreSlim.Release()  
  

Cuando todos los subprocesos han liberado el semáforo, el recuento está en el valor máximo especificado cuando se creó el semáforo.When all threads have released the semaphore, the count is at the maximum value specified when the semaphore was created. El recuento del semáforo está disponible en la propiedad CurrentCount.The semaphore's count is available from the CurrentCount property.

Important

La clase SemaphoreSlim no impone la identidad de subprocesos o tareas en las llamadas a los métodos Wait, WaitAsyncy Release.The SemaphoreSlim class doesn't enforce thread or task identity on calls to the Wait, WaitAsync, and Release methods. Además, si se utiliza el constructor SemaphoreSlim(Int32) para crear una instancia del objeto SemaphoreSlim, la propiedad CurrentCount puede aumentar más allá del valor establecido por el constructor.In addition, if the SemaphoreSlim(Int32) constructor is used to instantiate the SemaphoreSlim object, the CurrentCount property can increase beyond the value set by the constructor. Es responsabilidad del programador asegurarse de que las llamadas a métodos Wait o WaitAsync se emparejan adecuadamente con las llamadas a los métodos de Release.It is the programmer's responsibility to ensure that calls to Wait or WaitAsync methods are appropriately paired with calls to Release methods.

Constructors

SemaphoreSlim(Int32)

Inicializa una nueva instancia de la clase SemaphoreSlim, especificando el número inicial de solicitudes que se pueden conceder simultáneamente.Initializes a new instance of the SemaphoreSlim class, specifying the initial number of requests that can be granted concurrently.

SemaphoreSlim(Int32, Int32)

Inicializa una nueva instancia de la clase SemaphoreSlim, especificando el número inicial y máximo de solicitudes que se pueden conceder simultáneamente.Initializes a new instance of the SemaphoreSlim class, specifying the initial and maximum number of requests that can be granted concurrently.

Properties

AvailableWaitHandle

Devuelve un objeto WaitHandle que se puede usar para esperar en el semáforo.Returns a WaitHandle that can be used to wait on the semaphore.

CurrentCount

Obtiene el número de subprocesos restantes que puede introducir el objeto SemaphoreSlim.Gets the number of remaining threads that can enter the SemaphoreSlim object.

Methods

Dispose()

Libera todos los recursos usados por la instancia actual de la clase SemaphoreSlim.Releases all resources used by the current instance of the SemaphoreSlim class.

Dispose(Boolean)

Libera los recursos no administrados utilizados por el objeto SemaphoreSlim y, de forma opcional, libera los recursos administrados.Releases the unmanaged resources used by the SemaphoreSlim, and optionally releases the managed resources.

Equals(Object)

Determina si el objeto especificado es igual al objeto actual.Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode()

Sirve como la función hash predeterminada.Serves as the default hash function.

(Inherited from Object)
GetType()

Obtiene el Type de la instancia actual.Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone()

Crea una copia superficial del Object actual.Creates a shallow copy of the current Object.

(Inherited from Object)
Release()

Libera una vez el objeto SemaphoreSlim.Releases the SemaphoreSlim object once.

Release(Int32)

Libera el objeto SemaphoreSlim el número de veces especificado.Releases the SemaphoreSlim object a specified number of times.

ToString()

Devuelve una cadena que representa el objeto actual.Returns a string that represents the current object.

(Inherited from Object)
Wait()

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim.Blocks the current thread until it can enter the SemaphoreSlim.

Wait(CancellationToken)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, mientras se observa un elemento CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, while observing a CancellationToken.

Wait(Int32)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, usando un entero de 32 bits con signo que especifica el tiempo de espera.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout.

Wait(Int32, CancellationToken)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, usando un entero de 32 bits con signo que especifica el tiempo de espera mientras se observa un elemento CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout, while observing a CancellationToken.

Wait(TimeSpan)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, usando TimeSpan para especificar el tiempo de espera.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan to specify the timeout.

Wait(TimeSpan, CancellationToken)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, usando un TimeSpan que especifica el tiempo de espera mientras se observa un elemento CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan that specifies the timeout, while observing a CancellationToken.

WaitAsync()

De forma asincrónica espera que se introduzca SemaphoreSlim.Asynchronously waits to enter the SemaphoreSlim.

WaitAsync(CancellationToken)

De forma asincrónica, espera introducir SemaphoreSlim, mientras observa un elemento CancellationToken.Asynchronously waits to enter the SemaphoreSlim, while observing a CancellationToken.

WaitAsync(Int32)

De forma asincrónica espera que se introduzca SemaphoreSlim, usando un entero de 32 bits para medir el intervalo de tiempo.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval.

WaitAsync(Int32, CancellationToken)

De forma asincrónica, espera introducir SemaphoreSlim, usando un entero de 32 bits para medir el intervalo de tiempo, mientras observa un elemento CancellationToken.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval, while observing a CancellationToken.

WaitAsync(TimeSpan)

De forma asincrónica, espera introducir SemaphoreSlim, usando un TimeSpan para medir el intervalo de tiempo.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval.

WaitAsync(TimeSpan, CancellationToken)

De forma asincrónica, espera introducir SemaphoreSlim, usando un TimeSpan para medir el intervalo de tiempo, mientras observa un elemento CancellationToken.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval, while observing a CancellationToken.

Applies to

Thread Safety

Todos los miembros públicos y protegidos de SemaphoreSlim son seguros para subprocesos y se pueden usar simultáneamente desde varios subprocesos, con la excepción de Dispose(), que deben usarse solo cuando se hayan completado todas las demás operaciones de la SemaphoreSlim.All public and protected members of SemaphoreSlim are thread-safe and may be used concurrently from multiple threads, with the exception of Dispose(), which must be used only when all other operations on the SemaphoreSlim have completed.

See also