Condividi tramite


Semaphore Classe

Definizione

Limita il numero di thread che possono accedere simultaneamente a una risorsa o a un pool di risorse.

public ref class Semaphore sealed : System::Threading::WaitHandle
public sealed class Semaphore : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class Semaphore : System.Threading.WaitHandle
type Semaphore = class
    inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(false)>]
type Semaphore = class
    inherit WaitHandle
Public NotInheritable Class Semaphore
Inherits WaitHandle
Ereditarietà
Semaphore
Ereditarietà
Attributi

Esempio

Nell'esempio di codice seguente viene creato un semaforo con un numero massimo di tre e un conteggio iniziale pari a zero. L'esempio avvia cinque thread, che bloccano l'attesa del semaforo. Il thread principale usa l'overload del Release(Int32) metodo per aumentare il conteggio dei semafori al massimo, consentendo a tre thread di immettere il semaforo. Ogni thread usa il Thread.Sleep metodo per attendere un secondo, simulare il lavoro e quindi chiama l'overload del Release() metodo per rilasciare 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 viene aumentato leggermente per ogni thread, per semplificare la lettura dell'output.

#using <System.dll>
using namespace System;
using namespace System::Threading;

public ref class Example
{
private:
   // A semaphore that simulates a limited resource pool.
   //
   static Semaphore^ _pool;

   // A padding interval to make the output more orderly.
   static int _padding;

public:
   static void Main()
   {
      // Create a semaphore that can satisfy up to three
      // concurrent requests. Use an initial count of zero,
      // so that the entire semaphore count is initially
      // owned by the main program thread.
      //
      _pool = gcnew Semaphore( 0,3 );
      
      // Create and start five numbered threads.
      //
      for ( int i = 1; i <= 5; i++ )
      {
         Thread^ t = gcnew Thread(
            gcnew ParameterizedThreadStart( Worker ) );
         
         // Start the thread, passing the number.
         //
         t->Start( i );
      }
      
      // Wait for half a second, to allow all the
      // threads to start and to block on the semaphore.
      //
      Thread::Sleep( 500 );
      
      // The main thread starts out holding the entire
      // semaphore count. Calling Release(3) brings the
      // semaphore count back to its maximum value, and
      // allows the waiting threads to enter the semaphore,
      // up to three at a time.
      //
      Console::WriteLine( L"Main thread calls Release(3)." );
      _pool->Release( 3 );

      Console::WriteLine( L"Main thread exits." );
   }

private:
   static void Worker( Object^ num )
   {
      // Each worker thread begins by requesting the
      // semaphore.
      Console::WriteLine( L"Thread {0} begins and waits for the semaphore.", num );
      _pool->WaitOne();
      
      // A padding interval to make the output more orderly.
      int padding = Interlocked::Add( _padding, 100 );

      Console::WriteLine( L"Thread {0} enters the semaphore.", num );
      
      // The thread's "work" consists of sleeping for
      // about a second. Each thread "works" a little
      // longer, just to make the output more orderly.
      //
      Thread::Sleep( 1000 + padding );

      Console::WriteLine( L"Thread {0} releases the semaphore.", num );
      Console::WriteLine( L"Thread {0} previous semaphore count: {1}",
         num, _pool->Release() );
   }
};
using System;
using System.Threading;

public class Example
{
    // A semaphore that simulates a limited resource pool.
    //
    private static Semaphore _pool;

    // A padding interval to make the output more orderly.
    private static int _padding;

    public static void Main()
    {
        // Create a semaphore that can satisfy up to three
        // concurrent requests. Use an initial count of zero,
        // so that the entire semaphore count is initially
        // owned by the main program thread.
        //
        _pool = new Semaphore(initialCount: 0, maximumCount: 3);

        // Create and start five numbered threads. 
        //
        for(int i = 1; i <= 5; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Worker));

            // Start the thread, passing the number.
            //
            t.Start(i);
        }

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

        // The main thread starts out holding the entire
        // semaphore count. Calling Release(3) brings the 
        // semaphore count back to its maximum value, and
        // allows the waiting threads to enter the semaphore,
        // up to three at a time.
        //
        Console.WriteLine("Main thread calls Release(3).");
        _pool.Release(releaseCount: 3);

        Console.WriteLine("Main thread exits.");
    }

    private static void Worker(object num)
    {
        // Each worker thread begins by requesting the
        // semaphore.
        Console.WriteLine("Thread {0} begins " +
            "and waits for the semaphore.", num);
        _pool.WaitOne();

        // A padding interval to make the output more orderly.
        int padding = Interlocked.Add(ref _padding, 100);

        Console.WriteLine("Thread {0} enters the semaphore.", num);
        
        // The thread's "work" consists of sleeping for 
        // about a second. Each thread "works" a little 
        // longer, just to make the output more orderly.
        //
        Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}",
            num, _pool.Release());
    }
}
Imports System.Threading

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    ' A padding interval to make the output more orderly.
    Private Shared _padding As Integer

    <MTAThread> _
    Public Shared Sub Main()
        ' Create a semaphore that can satisfy up to three
        ' concurrent requests. Use an initial count of zero,
        ' so that the entire semaphore count is initially
        ' owned by the main program thread.
        '
        _pool = New Semaphore(0, 3)

        ' Create and start five numbered threads. 
        '
        For i As Integer = 1 To 5
            Dim t As New Thread(New ParameterizedThreadStart(AddressOf Worker))
            'Dim t As New Thread(AddressOf Worker)

            ' Start the thread, passing the number.
            '
            t.Start(i)
        Next i

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

        ' The main thread starts out holding the entire
        ' semaphore count. Calling Release(3) brings the 
        ' semaphore count back to its maximum value, and
        ' allows the waiting threads to enter the semaphore,
        ' up to three at a time.
        '
        Console.WriteLine("Main thread calls Release(3).")
        _pool.Release(3)

        Console.WriteLine("Main thread exits.")
    End Sub

    Private Shared Sub Worker(ByVal num As Object)
        ' Each worker thread begins by requesting the
        ' semaphore.
        Console.WriteLine("Thread {0} begins " _
            & "and waits for the semaphore.", num)
        _pool.WaitOne()

        ' A padding interval to make the output more orderly.
        Dim padding As Integer = Interlocked.Add(_padding, 100)

        Console.WriteLine("Thread {0} enters the semaphore.", num)
        
        ' The thread's "work" consists of sleeping for 
        ' about a second. Each thread "works" a little 
        ' longer, just to make the output more orderly.
        '
        Thread.Sleep(1000 + padding)

        Console.WriteLine("Thread {0} releases the semaphore.", num)
        Console.WriteLine("Thread {0} previous semaphore count: {1}", _
            num, _
            _pool.Release())
    End Sub
End Class

Commenti

Usare la Semaphore classe per controllare l'accesso a un pool di risorse. I thread immettono il semaforo chiamando il WaitOne metodo , ereditato dalla WaitHandle classe e rilasciando il semaforo chiamando il Release metodo .

Il conteggio su un semaforo viene decrementato ogni volta che un thread entra nel semaforo e incrementato quando un thread rilascia il semaforo. Quando il conteggio è zero, le richieste successive vengono bloccate fino a quando altri thread non rilasciano il semaforo. Quando tutti i thread hanno rilasciato il semaforo, il conteggio è al valore massimo specificato al momento della creazione del semaforo.

Non esiste un ordine garantito, ad esempio FIFO o LIFO, in cui i thread bloccati immettono il semaforo.

Un thread può immettere più volte il semaforo chiamando il WaitOne metodo ripetutamente. Per rilasciare alcune o tutte queste voci, il thread può chiamare l'overload del metodo senza Release() parametri più volte oppure può chiamare l'overload del Release(Int32) metodo che specifica il numero di voci da rilasciare.

La Semaphore classe non applica l'identità del thread alle chiamate a WaitOne o Release. È responsabilità del programmatore garantire che i thread non rilascino il semaforo troppe volte. Ad esempio, si consideri un semaforo con un conteggio massimo di due e il thread A e B accedano entrambi al semaforo. Se un errore di programmazione nel thread B lo chiama Release due volte, entrambe le chiamate hanno esito positivo. Il conteggio sul semaforo è completo e quando il thread A alla fine chiama Release, viene generata un'eccezione SemaphoreFullException.

I semafori sono di due tipi: semafori locali e semafori di sistema denominati. Se si crea un Semaphore oggetto utilizzando un costruttore che accetta un nome, viene associato a un semaforo del sistema operativo di tale nome. I semafori di sistema denominati sono visibili in tutto il sistema operativo e possono essere usati per sincronizzare le attività dei processi. È possibile creare più Semaphore oggetti che rappresentano lo stesso semaforo di sistema denominato ed è possibile usare il OpenExisting metodo per aprire un semaforo di sistema denominato esistente.

Un semaforo locale esiste solo all'interno del processo. Può essere usato da qualsiasi thread nel processo che abbia un riferimento all'oggetto Semaphore locale. Ogni Semaphore oggetto è un semaforo locale separato.

Attenzione

Per impostazione predefinita, un semaforo denominato non è limitato all'utente che lo ha creato. Altri utenti possono essere in grado di aprire e usare il semaforo, inclusa l'interazione con il semaforo acquisendo il semaforo più volte e non rilasciandolo. Per limitare l'accesso a utenti specifici, è possibile usare un overload del costruttore o SemaphoreAcl passare un oggetto SemaphoreSecurity durante la creazione del semaforo denominato. Evitare di usare semafori denominati senza restrizioni di accesso per i sistemi che potrebbero avere utenti non attendibili che eseguono codice.

Costruttori

Semaphore(Int32, Int32)

Inizializza una nuova istanza della classe Semaphore, specificando il numero di voci iniziale e il numero massimo di voci contemporanei.

Semaphore(Int32, Int32, String)

Inizializza una nuova istanza della classe Semaphore, specificando il numero di accessi iniziale e il numero massimo di accessi contemporanei, nonché indicando facoltativamente il nome di un oggetto semaforo di sistema.

Semaphore(Int32, Int32, String, Boolean)

Inizializza una nuova istanza della classe Semaphore, specificando il numero di accessi iniziale e il numero massimo di accessi contemporanei, indicando facoltativamente il nome di un oggetto semaforo di sistema e specificando una variabile che riceve un valore che indica se è stato creato un nuovo semaforo di sistema.

Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)

Inizializza una nuova istanza della classe Semaphore, specificando il numero iniziale di accessi e il numero massimo di accessi contemporanei, indicando facoltativamente il nome di un oggetto semaforo di sistema, specificando una variabile che riceve un valore che indica se è stato creato un nuovo semaforo di sistema e specificando la sicurezza del controllo di accesso per il semaforo di sistema.

Campi

WaitTimeout

Indica che si è verificato il timeout di un'operazione WaitAny(WaitHandle[], Int32, Boolean) prima della segnalazione di uno degli handle di attesa. Questo campo è costante.

(Ereditato da WaitHandle)

Proprietà

Handle
Obsoleti.
Obsoleti.

Ottiene o imposta l'handle nativo del sistema operativo.

(Ereditato da WaitHandle)
SafeWaitHandle

Ottiene o imposta l'handle nativo del sistema operativo.

(Ereditato da WaitHandle)

Metodi

Close()

Rilascia tutte le risorse contenute nell'oggetto WaitHandle corrente.

(Ereditato da WaitHandle)
CreateObjRef(Type)

Consente di creare un oggetto che contiene tutte le informazioni rilevanti necessarie per la generazione del proxy utilizzato per effettuare la comunicazione con un oggetto remoto.

(Ereditato da MarshalByRefObject)
Dispose()

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

(Ereditato da WaitHandle)
Dispose(Boolean)

Quando ne viene eseguito l'override in una classe derivata, libera le risorse non gestite usate da WaitHandle ed eventualmente di liberare le risorse gestite.

(Ereditato da WaitHandle)
Equals(Object)

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

(Ereditato da Object)
GetAccessControl()

Ottiene la sicurezza del controllo di accesso per un semaforo di sistema denominato.

GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetLifetimeService()
Obsoleti.

Consente di recuperare l'oggetto servizio di durata corrente per controllare i criteri di durata per l'istanza.

(Ereditato da MarshalByRefObject)
GetType()

Ottiene l'oggetto Type dell'istanza corrente.

(Ereditato da Object)
InitializeLifetimeService()
Obsoleti.

Ottiene un oggetto servizio di durata per controllare i criteri di durata per questa istanza.

(Ereditato da MarshalByRefObject)
MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.

(Ereditato da Object)
MemberwiseClone(Boolean)

Crea una copia dei riferimenti dell'oggetto MarshalByRefObject corrente.

(Ereditato da MarshalByRefObject)
OpenExisting(String)

Apre il semaforo denominato specificato, se esistente.

OpenExisting(String, SemaphoreRights)

Apre il semaforo denominato specificato, se esistente, con l'accesso di sicurezza desiderato.

Release()

Esce dal semaforo e restituisce il conteggio precedente.

Release(Int32)

Esce dal semaforo il numero di volte specificato e restituisce il conteggio precedente.

SetAccessControl(SemaphoreSecurity)

Imposta la sicurezza del controllo di accesso per un semaforo di sistema denominato.

ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.

(Ereditato da Object)
TryOpenExisting(String, Semaphore)

Apre il semaforo denominato specificato, se esistente, e restituisce un valore che indica se l'operazione è riuscita.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Apre il semaforo denominato specificato, se esistente, con l'accesso di sicurezza desiderato, e restituisce un valore che indica se l'operazione è riuscita.

WaitOne()

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale.

(Ereditato da WaitHandle)
WaitOne(Int32)

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo.

(Ereditato da WaitHandle)
WaitOne(Int32, Boolean)

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa.

(Ereditato da WaitHandle)
WaitOne(TimeSpan)

Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un valore TimeSpan per specificare l'intervallo di tempo.

(Ereditato da WaitHandle)
WaitOne(TimeSpan, Boolean)

Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un oggetto TimeSpan per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa.

(Ereditato da WaitHandle)

Implementazioni dell'interfaccia esplicita

IDisposable.Dispose()

Questa API supporta l'infrastruttura del prodotto e non è previsto che venga usata direttamente dal codice.

Rilascia tutte le risorse usate da WaitHandle.

(Ereditato da WaitHandle)

Metodi di estensione

GetAccessControl(Semaphore)

Restituisce i descrittori di sicurezza per l'oggetto semaphore specificato.

SetAccessControl(Semaphore, SemaphoreSecurity)

Imposta i descrittori di sicurezza per il semaforo specificato.

GetSafeWaitHandle(WaitHandle)

Ottiene l'handle sicuro per un handle di attesa nativo del sistema operativo.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Imposta un handle sicuro per un handle di attesa nativo del sistema operativo.

Si applica a

Thread safety

Questo tipo è thread-safe.

Vedi anche