SemaphoreSlim Clase

Definición

Representa una alternativa ligera a Semaphore que limita el número de subprocesos que pueden tener acceso a un recurso o grupo de recursos simultáneamente.

public ref class SemaphoreSlim : IDisposable
public class SemaphoreSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class SemaphoreSlim : IDisposable
type SemaphoreSlim = class
    interface IDisposable
[<System.Runtime.InteropServices.ComVisible(false)>]
type SemaphoreSlim = class
    interface IDisposable
Public Class SemaphoreSlim
Implements IDisposable
Herencia
SemaphoreSlim
Atributos
Implementaciones

Ejemplos

En el ejemplo siguiente se crea un semáforo con un recuento máximo de tres subprocesos y un recuento inicial de cero subprocesos. En el ejemplo se inician cinco tareas, lo que bloquea la espera del semáforo. El subproceso principal llama a la Release(Int32) sobrecarga para aumentar el número de semáforos a su máximo, lo que permite que tres tareas entren en el semáforo. Cada vez que se libera el semáforo, se muestra el recuento de semáforos anterior. Los mensajes de la consola realizan un seguimiento del uso del semáforo. El intervalo de trabajo simulado aumenta ligeramente para cada subproceso para facilitar la lectura de la salida.

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);
                
                int semaphoreCount;
                semaphore.Wait();
                try
                {
                    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);
                }
                finally {
                    semaphoreCount = semaphore.Release();
                }
                Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.",
                                  Task.CurrentId, semaphoreCount);
            });
        }

        // 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.

Comentarios

Los semáforos son de dos tipos: semáforos locales y semáforos del sistema con nombre. Los semáforos locales son locales para una aplicación, los semáforos del sistema son visibles en todo el sistema operativo y son adecuados para la sincronización entre procesos. SemaphoreSlim es una alternativa ligera a la Semaphore clase que no usa Windows semáforos de kernel. A diferencia de la Semaphore clase , la SemaphoreSlim clase no admite semáforos de sistema con nombre. Puede usarlo solo como semáforo local. La SemaphoreSlim clase es el semáforo recomendado para la sincronización dentro de una sola aplicación.

Un semáforo ligero controla el acceso a un grupo de recursos que es local para la aplicación. Al crear una instancia de un semáforo, puede especificar el número máximo de subprocesos que pueden escribir el semáforo simultáneamente. También se especifica el número inicial de subprocesos que pueden especificar el semáforo simultáneamente. Esto define el recuento del semáforo.

El recuento se disminuye cada vez que un subproceso entra en el semáforo e incrementa cada vez que un subproceso libera el semáforo. Para especificar el semáforo, un subproceso llama a una de las Wait sobrecargas o WaitAsync . Para liberar el semáforo, llama a una de las Release sobrecargas. Cuando el recuento alcanza cero, las llamadas posteriores a uno de los Wait métodos bloquean hasta que otros subprocesos liberan el semáforo. Si se bloquean varios subprocesos, no hay ningún orden garantizado, como FIFO o LIFO, que controla cuando los subprocesos entran en el semáforo.

La estructura básica del código que usa un semáforo para proteger los recursos es:

' 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 se encuentra en el valor máximo especificado cuando se creó el semáforo. El recuento del semáforo está disponible en la CurrentCount propiedad .

Importante

La SemaphoreSlim clase no aplica la identidad de subproceso o tarea en las llamadas a los Waitmétodos , WaitAsyncy Release . Además, si el SemaphoreSlim(Int32) constructor se usa para crear una instancia del SemaphoreSlim objeto, la CurrentCount propiedad puede aumentar más allá del valor establecido por el constructor. Es responsabilidad del programador asegurarse de que las llamadas a Wait los métodos o WaitAsync se emparejan correctamente con llamadas a Release métodos.

Constructores

SemaphoreSlim(Int32)

Inicializa una nueva instancia de la clase SemaphoreSlim, especificando el número inicial de solicitudes que se pueden conceder simultáneamente.

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.

Propiedades

AvailableWaitHandle

Devuelve un objeto WaitHandle que se puede usar para esperar en el semáforo.

CurrentCount

Obtiene el número de subprocesos restantes que puede introducir el objeto SemaphoreSlim.

Métodos

Dispose()

Libera todos los recursos usados por la instancia actual de la clase SemaphoreSlim.

Dispose(Boolean)

Libera los recursos no administrados utilizados por el objeto SemaphoreSlim y, de forma opcional, libera los recursos administrados.

Equals(Object)

Determina si el objeto especificado es igual que el objeto actual.

(Heredado de Object)
GetHashCode()

Sirve como la función hash predeterminada.

(Heredado de Object)
GetType()

Obtiene el Type de la instancia actual.

(Heredado de Object)
MemberwiseClone()

Crea una copia superficial del Object actual.

(Heredado de Object)
Release()

Libera una vez el objeto SemaphoreSlim.

Release(Int32)

Libera el objeto SemaphoreSlim un número especificado de veces.

ToString()

Devuelve una cadena que representa el objeto actual.

(Heredado de Object)
Wait()

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim.

Wait(CancellationToken)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, mientras se observa un elemento 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.

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.

Wait(TimeSpan)

Bloquea el subproceso actual hasta que pueda introducir SemaphoreSlim, usando TimeSpan para especificar el tiempo de espera.

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.

WaitAsync()

De forma asincrónica espera que se introduzca SemaphoreSlim.

WaitAsync(CancellationToken)

De forma asincrónica, espera introducir SemaphoreSlim, mientras observa un elemento CancellationToken.

WaitAsync(Int32)

De forma asincrónica espera que se introduzca SemaphoreSlim, usando un entero de 32 bits para medir el intervalo de tiempo.

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.

WaitAsync(TimeSpan)

De forma asincrónica, espera introducir SemaphoreSlim, usando un TimeSpan para medir el intervalo de tiempo.

WaitAsync(TimeSpan, CancellationToken)

De forma asincrónica, espera introducir SemaphoreSlim, usando un TimeSpan para medir el intervalo de tiempo, mientras observa un elemento CancellationToken.

Se aplica a

Seguridad para subprocesos

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 solo se debe usar cuando se hayan completado todas las demás operaciones de SemaphoreSlim .

Consulte también