Udostępnij za pośrednictwem


SemaphoreSlim Klasa

Definicja

Reprezentuje uproszczoną alternatywę Semaphore , która ogranicza liczbę wątków, które mogą jednocześnie uzyskiwać dostęp do zasobu lub puli zasobów.

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
Dziedziczenie
SemaphoreSlim
Atrybuty
Implementuje

Przykłady

Poniższy przykład tworzy semafor z maksymalną liczbą trzech wątków i początkową liczbą wątków zerowych. Przykład uruchamia pięć zadań, z których wszystkie bloku czekają na semafor. Główny wątek wywołuje przeciążenie, Release(Int32) aby zwiększyć liczbę semaforów do maksymalnej, co umożliwia trzy zadania wprowadzania semafora. Za każdym razem, gdy semafor zostanie wydany, zostanie wyświetlona poprzednia liczba semaforów. Komunikaty konsoli śledzą użycie semafora. Symulowany interwał pracy jest nieznacznie zwiększany dla każdego wątku, aby ułatwić odczytywanie danych wyjściowych.

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.

Uwagi

Semaphores są dwóch typów: lokalne semafory i nazwane semaphores systemu. Lokalne semaphores są lokalne dla aplikacji, semafory systemu są widoczne w całym systemie operacyjnym i są odpowiednie do synchronizacji między procesami. Jest SemaphoreSlim to uproszczona alternatywa Semaphore dla klasy, która nie używa Windows semaphores jądra. Semaphore W przeciwieństwie do klasy SemaphoreSlim klasa nie obsługuje nazwanych semaphores systemu. Można go użyć tylko jako semafora lokalnego. Klasa SemaphoreSlim jest zalecanym semaforem do synchronizacji w ramach jednej aplikacji.

Lekki semafor kontroluje dostęp do puli zasobów lokalnych dla aplikacji. Podczas tworzenia wystąpienia semafora można określić maksymalną liczbę wątków, które mogą jednocześnie wprowadzać semafor. Należy również określić początkową liczbę wątków, które mogą jednocześnie wprowadzać semafor. Definiuje liczbę semaforów.

Liczba jest dekrementowana za każdym razem, gdy wątek wchodzi do semafora i zwiększa się za każdym razem, gdy wątek zwalnia semafor. Aby wprowadzić semafor, wątek wywołuje jeden z Wait przeciążeń lub WaitAsync . Aby zwolnić semafor, wywołuje jeden z Release przeciążeń. Gdy liczba osiągnie zero, kolejne wywołania do jednego z bloków Wait metod, dopóki inne wątki nie zwolnią semafora. Jeśli wiele wątków jest zablokowanych, nie ma gwarantowanej kolejności, takiej jak FIFO lub LIFO, która kontroluje, gdy wątki wchodzą do semapora.

Podstawowa struktura kodu, która używa semafora do ochrony zasobów, to:

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

Gdy wszystkie wątki zwolniły semafor, liczba jest na maksymalnej wartości określonej podczas tworzenia semafora. Liczba semaforów jest dostępna z CurrentCount właściwości .

Ważne

Klasa SemaphoreSlim nie wymusza tożsamości wątku ani zadania na wywołaniach metod Wait, WaitAsynci Release . Ponadto jeśli SemaphoreSlim(Int32) konstruktor jest używany do tworzenia wystąpienia SemaphoreSlim obiektu, CurrentCount właściwość może wzrosnąć poza wartość ustawioną przez konstruktora. Jest to odpowiedzialność programisty za zapewnienie, że wywołania metody Wait lub WaitAsync są odpowiednio sparowane z wywołaniami do Release metod.

Konstruktory

SemaphoreSlim(Int32)

Inicjuje nowe wystąpienie SemaphoreSlim klasy, określając początkową liczbę żądań, które można udzielić jednocześnie.

SemaphoreSlim(Int32, Int32)

Inicjuje SemaphoreSlim nowe wystąpienie klasy, określając początkową i maksymalną liczbę żądań, które można udzielić jednocześnie.

Właściwości

AvailableWaitHandle

Zwraca element WaitHandle , który może służyć do oczekiwania na semafor.

CurrentCount

Pobiera liczbę pozostałych wątków, które mogą wprowadzać SemaphoreSlim obiekt.

Metody

Dispose()

Zwalnia wszystkie zasoby używane przez bieżące wystąpienie klasy SemaphoreSlim.

Dispose(Boolean)

Zwalnia niezarządzane zasoby używane przez SemaphoreSlimprogram i opcjonalnie zwalnia zasoby zarządzane.

Equals(Object)

Określa, czy dany obiekt jest taki sam, jak bieżący obiekt.

(Odziedziczone po Object)
GetHashCode()

Służy jako domyślna funkcja skrótu.

(Odziedziczone po Object)
GetType()

Type Pobiera wartość bieżącego wystąpienia.

(Odziedziczone po Object)
MemberwiseClone()

Tworzy płytkią kopię bieżącego Objectelementu .

(Odziedziczone po Object)
Release()

SemaphoreSlim Zwalnia obiekt raz.

Release(Int32)

SemaphoreSlim Zwalnia obiekt o określonej liczbie razy.

ToString()

Zwraca ciąg reprezentujący bieżący obiekt.

(Odziedziczone po Object)
Wait()

Blokuje bieżący wątek, dopóki nie będzie mógł wprowadzić elementu SemaphoreSlim.

Wait(CancellationToken)

Blokuje bieżący wątek, dopóki nie będzie mógł wejść do SemaphoreSlimklasy , obserwując element CancellationToken.

Wait(Int32)

Blokuje bieżący wątek, dopóki nie będzie mógł wprowadzić SemaphoreSlimelementu , używając 32-bitowej liczby całkowitej ze znakiem określającym limit czasu.

Wait(Int32, CancellationToken)

Blokuje bieżący wątek, dopóki nie będzie mógł wprowadzić SemaphoreSlimwartości , używając 32-bitowej liczby całkowitej ze znakiem CancellationToken, która określa limit czasu, obserwując element .

Wait(TimeSpan)

Blokuje bieżący wątek, dopóki nie będzie mógł wprowadzić parametru SemaphoreSlim, używając parametru , TimeSpan aby określić limit czasu.

Wait(TimeSpan, CancellationToken)

Blokuje bieżący wątek, dopóki nie będzie mógł wprowadzić SemaphoreSlimelementu , przy użyciu elementu TimeSpan , który określa limit czasu, obserwując CancellationTokenelement .

WaitAsync()

Asynchronicznie czeka na wprowadzenie elementu SemaphoreSlim.

WaitAsync(CancellationToken)

Asynchronicznie czeka na wprowadzenie SemaphoreSlimelementu , obserwując element CancellationToken.

WaitAsync(Int32)

Asynchronicznie oczekuje na wprowadzenie SemaphoreSlimwartości , używając 32-bitowej liczby całkowitej ze znakiem w celu zmierzenia interwału czasu.

WaitAsync(Int32, CancellationToken)

Asynchronicznie czeka na wprowadzenie SemaphoreSlimwartości , używając 32-bitowej liczby całkowitej ze znakiem CancellationToken, aby zmierzyć interwał czasu, obserwując element .

WaitAsync(TimeSpan)

Asynchronicznie czeka na wprowadzenie SemaphoreSlimelementu , używając elementu TimeSpan w celu zmierzenia interwału czasu.

WaitAsync(TimeSpan, CancellationToken)

Asynchronicznie czeka na wprowadzenie SemaphoreSlimelementu , używając elementu , TimeSpan aby zmierzyć interwał czasu, obserwując element CancellationToken.

Dotyczy

Bezpieczeństwo wątkowe

Wszystkie publiczne i chronione elementy członkowskie są SemaphoreSlim bezpieczne wątkowo i mogą być używane współbieżnie z wielu wątków, z wyjątkiem Dispose(), które muszą być używane tylko wtedy, gdy wszystkie inne operacje na SemaphoreSlim obiekcie zostały ukończone.

Zobacz też