Teilen über


Semaphore Klasse

Definition

Schränkt die Anzahl von Threads ein, die gleichzeitig auf eine Ressource oder einen Pool von Ressourcen zugreifen können.

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
Vererbung
Semaphore
Vererbung
Attribute

Beispiele

Im folgenden Codebeispiel wird ein Semaphor mit einer maximalen Anzahl von drei und einer anfänglichen Anzahl von 0 (null) erstellt. Im Beispiel werden fünf Threads gestartet, die auf den Semaphor warten. Der Standard Thread verwendet die Release(Int32) Methodenüberladung, um die Semaphoranzahl auf ihr Maximum zu erhöhen, sodass drei Threads in den Semaphor gelangen können. Jeder Thread verwendet die Thread.Sleep -Methode, um eine Sekunde zu warten, die Arbeit zu simulieren, und ruft dann die Release() Methodenüberladung auf, um das Semaphor freizugeben. Jedes Mal, wenn der Semaphor freigesetzt wird, wird die vorherige Semaphoranzahl angezeigt. Konsolennachrichten verfolgen die Verwendung von Semaphor. Das simulierte Arbeitsintervall wird für jeden Thread geringfügig erhöht, um die Lesbarkeit der Ausgabe zu erleichtern.

#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

Hinweise

Verwenden Sie die -Klasse, um den Semaphore Zugriff auf einen Ressourcenpool zu steuern. Threads gelangen in den Semaphor, indem sie die WaitOne Methode aufrufen, die von der WaitHandle -Klasse geerbt wird, und das Semaphor durch Aufrufen der Release -Methode freigeben.

Die Anzahl eines Semaphors wird bei jedem Eintritt eines Threads in den Semaphor dekrementiert und erhöht, wenn ein Thread den Semaphor freigibt. Wenn die Anzahl null ist, werden nachfolgende Anforderungen blockiert, bis andere Threads das Semaphor freigeben. Wenn alle Threads das Semaphor freigegeben haben, liegt die Anzahl an dem maximalen Wert, der beim Erstellen des Semaphors angegeben wurde.

Es gibt keine garantierte Reihenfolge, z. B. FIFO oder LIFO, in der blockierte Threads in den Semaphor gelangen.

Ein Thread kann den Semaphor mehrmals eingeben, indem die WaitOne -Methode wiederholt aufgerufen wird. Um einige oder alle dieser Einträge freizugeben, kann der Thread die parameterlose Release() Methodenüberladung mehrmals aufrufen, oder er kann die Release(Int32) Methodenüberladung aufrufen, die die Anzahl der freizugebenden Einträge angibt.

Die Semaphore -Klasse erzwingt keine Threadidentität bei Aufrufen von WaitOne oder Release. Es liegt in der Verantwortung des Programmierers sicherzustellen, dass Threads den Semaphor nicht zu oft freigeben. Angenommen, ein Semaphor hat einen maximalen Zähler von zwei und Thread A sowie Thread B wechseln beide in das Semaphor. Wenn ein Programmierfehler in Thread B dazu führt, dass Release zweimal aufgerufen wird, sind beide Aufrufe erfolgreich. Der Zähler des Semaphors ist voll, und wenn Thread A schließlich Release aufruft, wird eine SemaphoreFullException ausgelöst.

Semaphore sind von zwei Typen: lokale Semaphore und benannte Systemsemaphore. Wenn Sie ein Semaphore Objekt mit einem Konstruktor erstellen, der einen Namen akzeptiert, wird es einem Betriebssystem-Semaphor dieses Namens zugeordnet. Benannte System-Semaphore sind im gesamten Betriebssystem sichtbar und können verwendet werden, um die Aktivitäten von Prozessen zu synchronisieren. Sie können mehrere Semaphore Objekte erstellen, die denselben benannten Systemsemaphor darstellen, und Sie können die OpenExisting -Methode verwenden, um ein vorhandenes benanntes Systemsemaphor zu öffnen.

Ein lokales Semaphor ist nur innerhalb Ihres Prozesses vorhanden. Er kann von jedem Thread in einem Prozess verwendet werden, der einen Verweis auf das lokale Semaphore-Objekt enthält. Jedes Semaphore Objekt ist ein separates lokales Semaphor.

Achtung

Standardmäßig ist ein benannter Semaphor nicht auf den Benutzer beschränkt, der es erstellt hat. Andere Benutzer sind möglicherweise in der Lage, den Semaphor zu öffnen und zu verwenden, einschließlich der Interferenz mit dem Semaphor, indem sie den Semaphor mehrmals erwerben und nicht freigeben. Um den Zugriff auf bestimmte Benutzer einzuschränken, können Sie eine Konstruktorüberladung oder verwenden SemaphoreAcl und beim Erstellen des benannten Semaphors eine SemaphoreSecurity übergeben. Vermeiden Sie die Verwendung benannter Semaphore ohne Zugriffsbeschränkungen auf Systemen, auf denen möglicherweise nicht vertrauenswürdige Benutzer Code ausführen.

Konstruktoren

Semaphore(Int32, Int32)

Initialisiert eine neue Instanz der Semaphore-Klasse und gibt die ursprüngliche Anzahl von Einträgen und die maximale Anzahl von gleichzeitigen Einträgen an.

Semaphore(Int32, Int32, String)

Initialisiert eine neue Instanz der Semaphore-Klasse, gibt die ursprüngliche Anzahl von Einträgen und die maximale Anzahl von gleichzeitigen Einträgen sowie optional den Namen eines Systemsemaphorobjekts an.

Semaphore(Int32, Int32, String, Boolean)

Initialisiert eine neue Instanz der Semaphore-Klasse, gibt die ursprüngliche Anzahl von Einträgen und die maximale Anzahl von gleichzeitigen Einträgen sowie optional den Namen eines Systemsemaphorobjekts an, gibt eine Variable an, die einen Wert empfängt, der angibt, ob ein neues Systemsemaphor erstellt wurde.

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

Initialisiert eine neue Instanz der Semaphore-Klasse, gibt die ursprüngliche Anzahl von Einträgen und die maximale Anzahl von gleichzeitigen Einträgen an, gibt optional den Namen eines Systemsemaphorobjekts an, gibt eine Variable an, die einen Wert empfängt, der angibt, ob ein neues Systemsemaphor erstellt wurde, und gibt die Sicherheitszugriffssteuerung für das Systemsemaphor an.

Felder

WaitTimeout

Gibt an, dass ein Timeout für einen WaitAny(WaitHandle[], Int32, Boolean)-Vorgang überschritten wurde, bevor ein Signal an eines der WaitHandles gesendet wurde. Dieses Feld ist konstant.

(Geerbt von WaitHandle)

Eigenschaften

Handle
Veraltet.
Veraltet.

Ruft das systemeigene Betriebssystemhandle auf oder legt dieses fest.

(Geerbt von WaitHandle)
SafeWaitHandle

Ruft das systemeigene Betriebssystemhandle auf oder legt dieses fest.

(Geerbt von WaitHandle)

Methoden

Close()

Gibt alle von der aktuellen WaitHandle-Klasse reservierten Ressourcen frei.

(Geerbt von WaitHandle)
CreateObjRef(Type)

Erstellt ein Objekt mit allen relevanten Informationen, die zum Generieren eines Proxys für die Kommunikation mit einem Remoteobjekt erforderlich sind.

(Geerbt von MarshalByRefObject)
Dispose()

Gibt alle von der aktuellen Instanz der WaitHandle-Klasse verwendeten Ressourcen frei.

(Geerbt von WaitHandle)
Dispose(Boolean)

Gibt beim Überschreiben in einer abgeleiteten Klasse die von WaitHandle verwendeten nicht verwalteten Ressourcen und optional die verwalteten Ressourcen frei.

(Geerbt von WaitHandle)
Equals(Object)

Bestimmt, ob das angegebene Objekt gleich dem aktuellen Objekt ist.

(Geerbt von Object)
GetAccessControl()

Ruft die Zugriffssteuerungssicherheit für ein benanntes Systemsemaphor ab.

GetHashCode()

Fungiert als Standardhashfunktion.

(Geerbt von Object)
GetLifetimeService()
Veraltet.

Ruft das aktuelle Lebensdauerdienstobjekt ab, das die Lebensdauerrichtlinien für diese Instanz steuert.

(Geerbt von MarshalByRefObject)
GetType()

Ruft den Type der aktuellen Instanz ab.

(Geerbt von Object)
InitializeLifetimeService()
Veraltet.

Ruft ein Lebensdauerdienstobjekt zur Steuerung der Lebensdauerrichtlinie für diese Instanz ab.

(Geerbt von MarshalByRefObject)
MemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.

(Geerbt von Object)
MemberwiseClone(Boolean)

Erstellt eine flache Kopie des aktuellen MarshalByRefObject-Objekts.

(Geerbt von MarshalByRefObject)
OpenExisting(String)

Öffnet das angegebene benannte Semaphor, wenn es bereits vorhanden ist.

OpenExisting(String, SemaphoreRights)

Öffnet die angegebene benannte Semaphore, wenn sie bereits vorhanden ist, mit dem gewünschten Sicherheitszugriff.

Release()

Beendet das Semaphor und gibt die vorherige Anzahl zurück.

Release(Int32)

Gibt das Semaphor eine festgelegte Anzahl von Malen frei und gibt den vorherigen Zähler zurück.

SetAccessControl(SemaphoreSecurity)

Legt die Zugriffssteuerungssicherheit für ein benanntes Systemsemaphor fest.

ToString()

Gibt eine Zeichenfolge zurück, die das aktuelle Objekt darstellt.

(Geerbt von Object)
TryOpenExisting(String, Semaphore)

Öffnet das angegebene benannte Semaphor, wenn es bereits vorhanden ist, und gibt einen Wert zurück, der angibt, ob der Vorgang erfolgreich war.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Öffnet das angegebene benannte Semaphor, wenn es bereits mit dem gewünschten Sicherheitszugriff vorhanden ist und gibt einen Wert zurück, der angibt, ob der Vorgang erfolgreich war.

WaitOne()

Blockiert den aktuellen Thread, bis das aktuelle WaitHandle ein Signal empfängt.

(Geerbt von WaitHandle)
WaitOne(Int32)

Blockiert den aktuellen Thread, bis das aktuelle WaitHandle ein Signal empfängt, wobei eine 32-Bit-Ganzzahl mit Vorzeichen zum Angeben des Zeitintervalls in Millisekunden verwendet wird.

(Geerbt von WaitHandle)
WaitOne(Int32, Boolean)

Blockiert den aktuellen Thread, bis das aktuelle WaitHandle ein Signal empfängt, wobei eine 32-Bit-Ganzzahl mit Vorzeichen zum Angeben des Zeitintervalls verwendet und angegeben wird, ob die Synchronisierungsdomäne vor dem Wartevorgang verlassen werden soll.

(Geerbt von WaitHandle)
WaitOne(TimeSpan)

Blockiert den aktuellen Thread, bis die aktuelle Instanz ein Signal empfängt, wobei eine TimeSpan zum Angeben des Zeitintervalls verwendet wird.

(Geerbt von WaitHandle)
WaitOne(TimeSpan, Boolean)

Blockiert den aktuellen Thread, bis die aktuelle Instanz ein Signal empfängt, wobei eine TimeSpan zum Angeben des Zeitintervalls verwendet und angegeben wird, ob die Synchronisierungsdomäne vor dem Wartevorgang verlassen werden soll.

(Geerbt von WaitHandle)

Explizite Schnittstellenimplementierungen

IDisposable.Dispose()

Diese API unterstützt die Produktinfrastruktur und ist nicht für die direkte Verwendung aus Ihrem Code gedacht.

Gibt alle vom WaitHandle verwendeten Ressourcen frei.

(Geerbt von WaitHandle)

Erweiterungsmethoden

GetAccessControl(Semaphore)

Gibt die Sicherheitsbeschreibungen für den angegebenen semaphore zurück.

SetAccessControl(Semaphore, SemaphoreSecurity)

Legt die Sicherheitsbeschreibungen für den angegebenen Semaphor fest.

GetSafeWaitHandle(WaitHandle)

Ruft das sichere Handle für ein systemeigenes Betriebssystem-Wait-Handle ab.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Stellt ein sicheres Handle für ein systemeigenes Betriebssystem-Wait-Handle ein.

Gilt für:

Threadsicherheit

Dieser Typ ist threadsicher.

Weitere Informationen