SemaphoreSlim Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
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.