SemaphoreSlim Klasse

Definition

Eine einfache Alternative zu Semaphore, die die Anzahl der Threads beschränkt, die gleichzeitig auf eine Ressource oder einen Ressourcenpool zugreifen können.

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
Vererbung
SemaphoreSlim
Attribute
Implementiert

Beispiele

Im folgenden Beispiel wird ein Semaphor mit einer maximalen Anzahl von drei Threads und einer anfänglichen Anzahl von 0 Threads erstellt. Im Beispiel werden fünf Aufgaben gestartet, die alle auf den Semaphor warten. Der Hauptthread ruft die Release(Int32) -Überladung auf, um die Semaphoranzahl auf ihr Maximum zu erhöhen, sodass drei Aufgaben in den Semaphor gelangen können. 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 Ausgabe einfacher zu lesen.

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.

Hinweise

Semaphore sind von zwei Typen: lokale Semaphore und benannte Systemsemaphore. Lokale Semaphore sind für eine Anwendung lokal, System-Semaphore sind im gesamten Betriebssystem sichtbar und eignen sich für die prozessübergreifende Synchronisierung. ist SemaphoreSlim eine einfache Alternative zur -Klasse, die Semaphore keine Windows-Kernel-Semaphore verwendet. Semaphore Im Gegensatz zur -Klasse unterstützt die SemaphoreSlim Klasse keine benannten Systemsemaphore. Sie können es nur als lokales Semaphor verwenden. Die SemaphoreSlim -Klasse ist der empfohlene Semaphor für die Synchronisierung innerhalb einer einzelnen App.

Ein schlanker Semaphor steuert den Zugriff auf einen Ressourcenpool, der für Ihre Anwendung lokal ist. Wenn Sie ein Semaphor instanziieren, können Sie die maximale Anzahl von Threads angeben, die gleichzeitig in das Semaphor gelangen können. Sie geben auch die anfängliche Anzahl von Threads an, die gleichzeitig in den Semaphor gelangen können. Dadurch wird die Anzahl des Semaphors definiert.

Die Anzahl wird jedes Mal dekrementiert, wenn ein Thread in den Semaphor eintritt, und es wird jedes Mal erhöht, wenn ein Thread den Semaphor freigibt. Zum Eingeben des Semaphors ruft ein Thread eine der Wait -Überladungen oder WaitAsync auf. Um den Semaphor freizugeben, ruft er eine der Release Überladungen auf. Wenn die Anzahl null erreicht, werden nachfolgende Aufrufe einer der Wait Methoden blockiert, bis andere Threads den Semaphor freigeben. Wenn mehrere Threads blockiert werden, gibt es keine garantierte Reihenfolge, z. B. FIFO oder LIFO, die steuert, wann Threads in den Semaphor gelangen.

Die grundlegende Struktur für Code, der einen Semaphor zum Schutz von Ressourcen verwendet, ist:

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

Wenn alle Threads das Semaphor freigegeben haben, liegt die Anzahl an dem maximalen Wert, der beim Erstellen des Semaphors angegeben wurde. Die Anzahl des Semaphors ist über die CurrentCount -Eigenschaft verfügbar.

Wichtig

Die SemaphoreSlim -Klasse erzwingt keine Thread- oder Taskidentität bei Aufrufen der WaitMethoden , WaitAsyncund Release . Wenn der SemaphoreSlim(Int32) -Konstruktor zum Instanziieren des SemaphoreSlim -Objekts verwendet wird, kann die CurrentCount -Eigenschaft darüber hinaus den vom Konstruktor festgelegten Wert erhöhen. Es liegt in der Verantwortung des Programmierers sicherzustellen, dass Aufrufe von Wait oder WaitAsync Methoden ordnungsgemäß mit Aufrufen von Release Methoden gekoppelt werden.

Konstruktoren

SemaphoreSlim(Int32)

Initialisiert eine neue Instanz der SemaphoreSlim-Klasse und gibt die ursprüngliche Anzahl von Anforderungen an, die gleichzeitig gewährt werden können.

SemaphoreSlim(Int32, Int32)

Initialisiert eine neue Instanz der SemaphoreSlim-Klasse und gibt die ursprüngliche sowie die maximale Anzahl von Anforderungen an, die gleichzeitig gewährt werden können.

Eigenschaften

AvailableWaitHandle

Gibt ein WaitHandle zurück, das verwendet werden kann um auf die Semaphore zu warten.

CurrentCount

Ruft die Anzahl der verbleibenden Threads ab, für die das Eintreten in das SemaphoreSlim-Objekt zulässig ist.

Methoden

Dispose()

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

Dispose(Boolean)

Gibt die von SemaphoreSlim verwendeten nicht verwalteten Ressourcen und optional die verwalteten Ressourcen frei.

Equals(Object)

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

(Geerbt von Object)
GetHashCode()

Fungiert als Standardhashfunktion.

(Geerbt von Object)
GetType()

Ruft den Type der aktuellen Instanz ab.

(Geerbt von Object)
MemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.

(Geerbt von Object)
Release()

Gibt das SemaphoreSlim-Objekt einmal frei.

Release(Int32)

Gibt das SemaphoreSlim-Objekt eine festgelegte Anzahl von Malen frei.

ToString()

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

(Geerbt von Object)
Wait()

Blockiert den aktuellen Thread, bis er in SemaphoreSlim eintreten kann.

Wait(CancellationToken)

Blockiert den aktuellen Thread, bis er in die Warteschlange von SemaphoreSlim eingereiht werden kann, wobei ein CancellationToken überwacht wird.

Wait(Int32)

Blockiert den aktuellen Thread, bis er in die Warteschlange von SemaphoreSlim eingereiht werden kann, wobei das Timeout mit einer 32-Bit-Ganzzahl mit Vorzeichen angegeben wird.

Wait(Int32, CancellationToken)

Blockiert den aktuellen Thread, bis er in die Warteschlange von SemaphoreSlim eingereiht werden kann, wobei eine 32-Bit-Ganzzahl mit Vorzeichen zum Angeben des Timeouts verwendet und ein CancellationToken überwacht wird.

Wait(TimeSpan)

Blockiert den aktuellen Thread, bis er in die Warteschlange von SemaphoreSlim eingereiht werden kann, wobei ein TimeSpan zum Angeben des Timeouts verwendet wird.

Wait(TimeSpan, CancellationToken)

Blockiert den aktuellen Thread, bis er in die Warteschlange von SemaphoreSlim eingereiht werden kann, wobei eine TimeSpan den Timeout angibt und ein CancellationToken überwacht wird.

WaitAsync()

Wartet asynchron auf den Eintritt in SemaphoreSlim.

WaitAsync(CancellationToken)

Wartet asynchron auf den Zutritt zum SemaphoreSlim, während ein ein CancellationToken beobachtet wird.

WaitAsync(Int32)

Wartet asynchron auf den Zutritt zum SemaphoreSlim, wobei eine 32-Bit-Ganzzahl mit Vorzeichen zum Messen des Zeitintervalls verwendet wird.

WaitAsync(Int32, CancellationToken)

Wartet asynchron auf den Zutritt zum SemaphoreSlim, wobei eine 32-Bit-Ganzzahl mit Vorzeichen zum Messen des Zeitintervalls verwendet wird, während ein CancellationToken beobachtet wird.

WaitAsync(TimeSpan)

Wartet asynchron auf den Zutritt zum SemaphoreSlim unter Verwendung einer TimeSpan zum Messen des Zeitintervalls.

WaitAsync(TimeSpan, CancellationToken)

Wartet asynchron auf den Zutritt zum SemaphoreSlim unter Verwendung einer TimeSpan zum Messen des Zeitintervalls, während ein CancellationToken beobachtet wird.

Gilt für:

Threadsicherheit

Alle öffentlichen und geschützten Member von SemaphoreSlim sind threadsicher und können gleichzeitig von mehreren Threads verwendet werden, mit Ausnahme von Dispose(), die nur verwendet werden dürfen, wenn alle anderen Vorgänge für abgeschlossen SemaphoreSlim sind.

Weitere Informationen