SemaphoreSlim Classe

Definizione

Rappresenta un'alternativa semplificata a Semaphore che limita il numero di thread che possono accedere simultaneamente a una risorsa o a un pool di risorse.

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
Ereditarietà
SemaphoreSlim
Attributi
Implementazioni

Esempio

Nell'esempio seguente viene creato un semaforo con un numero massimo di tre thread e un numero iniziale di thread zero. L'esempio avvia cinque attività, tutte in attesa del semaforo. Il thread principale chiama l'overload per aumentare il Release(Int32) conteggio dei semafori al massimo, che consente a tre attività di immettere il semaforo. Ogni volta che viene rilasciato il semaforo, viene visualizzato il conteggio del semaforo precedente. I messaggi della console tengono traccia dell'uso del semaforo. L'intervallo di lavoro simulato è aumentato leggermente per ogni thread per semplificare la lettura dell'output.

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.

Commenti

I semafori sono di due tipi: semafori locali e semafori di sistema denominati. I semafori locali sono locali per un'applicazione, i semafori di sistema sono visibili in tutto il sistema operativo e sono adatti per la sincronizzazione tra processi. L'oggetto SemaphoreSlim è un'alternativa leggera alla Semaphore classe che non usa Windows semafori del kernel. A differenza della classe, la Semaphore SemaphoreSlim classe non supporta i semafori di sistema denominati. È possibile usarlo solo come semaforo locale. La SemaphoreSlim classe è il semaforo consigliato per la sincronizzazione all'interno di una singola app.

Un semaforo leggero controlla l'accesso a un pool di risorse locali per l'applicazione. Quando si crea un'istanza di un semaforo, è possibile specificare il numero massimo di thread che possono immettere il semaforo simultaneamente. Si specifica anche il numero iniziale di thread che possono immettere il semaforo simultaneamente. Questo definisce il conteggio del semaforo.

Il conteggio viene decrementato ogni volta che un thread entra nel semaforo e viene incrementato ogni volta che un thread rilascia il semaforo. Per immettere il semaforo, un thread chiama uno degli Wait overload o WaitAsync . Per rilasciare il semaforo, chiama uno degli Release overload. Quando il conteggio raggiunge zero, le chiamate successive a uno dei Wait metodi bloccano fino a quando altri thread rilasciano il semaforo. Se più thread vengono bloccati, non esiste alcun ordine garantito, ad esempio FIFO o LIFO, che controlla quando i thread entrano nel semaforo.

La struttura di base per il codice che usa un semaforo per proteggere le risorse è:

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

Quando tutti i thread hanno rilasciato il semaforo, il conteggio è al valore massimo specificato quando è stato creato il semaforo. Il conteggio del semaforo è disponibile dalla CurrentCount proprietà.

Importante

La SemaphoreSlim classe non applica l'identità del thread o dell'attività Waitalle chiamate ai metodi , WaitAsynce Release . Inoltre, se il costruttore viene usato per creare un'istanza dell'oggettoSemaphoreSlim, la SemaphoreSlim(Int32) CurrentCount proprietà può aumentare oltre il valore impostato dal costruttore. È responsabilità del programmatore assicurarsi che le chiamate a o WaitAsync i metodi siano associate in modo appropriato alle chiamate ai Wait Release metodi.

Costruttori

SemaphoreSlim(Int32)

Inizializza una nuova istanza della classe SemaphoreSlim specificando il numero iniziale di richieste che possono essere concesse simultaneamente.

SemaphoreSlim(Int32, Int32)

Inizializza una nuova istanza della classe SemaphoreSlim specificando il numero iniziale e massimo di richieste che possono essere concesse simultaneamente.

Proprietà

AvailableWaitHandle

Restituisce un oggetto WaitHandle che può essere usato per attendere il semaforo.

CurrentCount

Ottiene il numero di thread rimanenti che possono accedere all'oggetto SemaphoreSlim.

Metodi

Dispose()

Rilascia tutte le risorse usate dall'istanza corrente della classe SemaphoreSlim.

Dispose(Boolean)

Rilascia le risorse non gestite usate dall'oggetto SemaphoreSlim e, facoltativamente, le risorse gestite.

Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.

(Ereditato da Object)
GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetType()

Ottiene l'oggetto Type dell'istanza corrente.

(Ereditato da Object)
MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.

(Ereditato da Object)
Release()

Rilascia l'oggetto SemaphoreSlim una volta.

Release(Int32)

Rilascia l'oggetto SemaphoreSlim un numero di volte specificato.

ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.

(Ereditato da Object)
Wait()

Blocca il thread corrente finché non può immettere SemaphoreSlim.

Wait(CancellationToken)

Blocca il thread corrente finché non può accedere all'oggetto SemaphoreSlim osservando un oggetto CancellationToken.

Wait(Int32)

Blocca il thread corrente finché non può accedere all'oggetto SemaphoreSlim, usando un intero con segno a 32 bit che specifica il timeout.

Wait(Int32, CancellationToken)

Blocca il thread corrente finché non può accedere all'oggetto SemaphoreSlim, usando un intero con segno a 32 bit che specifica il timeout e osservando un oggetto CancellationToken.

Wait(TimeSpan)

Blocca il thread corrente finché non può accedere all'oggetto SemaphoreSlim, usando un oggetto TimeSpan per specificare il timeout.

Wait(TimeSpan, CancellationToken)

Blocca il thread corrente finché non può accedere all'oggetto SemaphoreSlim, usando un oggetto TimeSpan che specifica il timeout e osservando un oggetto CancellationToken.

WaitAsync()

Attende in modo asincrono di immettere SemaphoreSlim.

WaitAsync(CancellationToken)

Attende in modo asincrono di accedere all'oggetto SemaphoreSlim, osservando un oggetto CancellationToken.

WaitAsync(Int32)

Attende in modo asincrono di accedere all'oggetto SemaphoreSlim, usando un intero con segno a 32 bit per misurare l'intervallo di tempo.

WaitAsync(Int32, CancellationToken)

Attende in modo asincrono di accedere all'oggetto SemaphoreSlim, usando un intero con segno a 32 bit per misurare l'intervallo di tempo e osservando un oggetto CancellationToken.

WaitAsync(TimeSpan)

Attende in modo asincrono di accedere all'oggetto SemaphoreSlim, usando un oggetto TimeSpan per misurare l'intervallo di tempo.

WaitAsync(TimeSpan, CancellationToken)

Attende in modo asincrono di accedere all'oggetto SemaphoreSlim, usando un oggetto TimeSpan per misurare l'intervallo di tempo e osservando un oggetto CancellationToken.

Si applica a

Thread safety

Tutti i membri pubblici e protetti di sono thread-safe e possono essere usati simultaneamente da più thread, ad eccezione di SemaphoreSlim Dispose(), che deve essere usato solo quando tutte le altre operazioni sul SemaphoreSlim sono state completate.

Vedi anche