SemaphoreSlim Classe
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Representa uma alternativa leve que Semaphore limita o número de threads que podem aceder a um recurso ou conjunto de recursos em simultâneo.
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
- Herança
-
SemaphoreSlim
- Atributos
- Implementações
Exemplos
O exemplo seguinte cria um semáforo com uma contagem máxima de três threads e uma contagem inicial de zero threads. O exemplo inicia cinco tarefas, todas bloqueadas à espera do semáforo. O thread principal chama a Release(Int32) sobrecarga para aumentar o número de semáforos ao máximo, permitindo que três tarefas entrem no semáforo. Cada vez que o semáforo é libertado, é apresentada a contagem anterior de semáforos. As mensagens de consola acompanham o uso de semáforos. O intervalo de trabalho simulado é ligeiramente aumentado para cada thread para facilitar a leitura da saída.
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.
Observações
Os semáforos são de dois tipos: semáforos locais e semáforos de sistemas nomeados. Os semáforos locais são locais para uma aplicação, os semáforos do sistema são visíveis por todo o sistema operativo e são adequados para sincronização entre processos. O SemaphoreSlim é uma alternativa leve à classe Semaphore que não utiliza semáforos Windows kernel. Ao contrário da Semaphore classe, esta SemaphoreSlim não suporta semáforos de sistemas nomeados. Podes usá-lo apenas como semáforo local. A SemaphoreSlim classe é o semáforo recomendado para sincronização dentro de uma única aplicação.
Um semáforo leve controla o acesso a um conjunto de recursos local para a sua aplicação. Quando instancias um semáforo, podes especificar o número máximo de threads que podem entrar no semáforo em simultâneo. Também especificas o número inicial de threads que podem entrar no semáforo em simultâneo. Isto define a contagem do semáforo.
A contagem é decrementada cada vez que um fio entra no semáforo, e incrementada cada vez que um fio liberta o semáforo. Para entrar no semáforo, um fio chama uma das Wait sobrecargas de ou WaitAsync . Para libertar o semáforo, chama uma das Release sobrecargas. Quando a contagem atinge zero, chamadas subsequentes a um dos Wait métodos bloqueiam-se até que outros threads libertem o semáforo. Se múltiplos threads estiverem bloqueados, não existe uma ordem garantida, como FIFO ou LIFO, que controle quando os threads entram no semáforo.
A estrutura básica para código que utiliza um semáforo para proteger recursos é:
' Enter semaphore by calling one of the Wait or WaitAsync methods.
SemaphoreSlim.Wait()
'
' Execute code protected by the semaphore.
'
SemaphoreSlim.Release()
Quando todas as threads libertam o semáforo, a contagem está no valor máximo especificado quando o semáforo foi criado. A contagem do semáforo está disponível na CurrentCount propriedade.
Importante
A SemaphoreSlim classe não impõe identidade de thread ou tarefa nas chamadas aos Waitmétodos , WaitAsync, e Release . Além disso, se o SemaphoreSlim(Int32) construtor for usado para instanciar o SemaphoreSlim objeto, a CurrentCount propriedade pode aumentar para além do valor definido pelo construtor. É responsabilidade do programador garantir que as chamadas para Wait ou WaitAsync métodos são adequadamente associadas a chamadas para Release métodos.
Construtores
| Name | Description |
|---|---|
| SemaphoreSlim(Int32, Int32) |
Inicializa uma nova instância da SemaphoreSlim classe, especificando o número inicial e máximo de pedidos que podem ser concedidos simultaneamente. |
| SemaphoreSlim(Int32) |
Inicializa uma nova instância da SemaphoreSlim classe, especificando o número inicial de pedidos que podem ser concedidos simultaneamente. |
Propriedades
| Name | Description |
|---|---|
| AvailableWaitHandle |
Devolve um WaitHandle que pode ser usado para esperar pelo semáforo. |
| CurrentCount |
Obtém o número de threads restantes que podem entrar no SemaphoreSlim objeto. |
Métodos
| Name | Description |
|---|---|
| Dispose() |
Liberta todos os recursos usados pela instância atual da SemaphoreSlim classe. |
| Dispose(Boolean) |
Liberta os recursos não geridos usados pelo SemaphoreSlim, e opcionalmente liberta os recursos geridos. |
| Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
| GetHashCode() |
Serve como função de hash predefinida. (Herdado de Object) |
| GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
| MemberwiseClone() |
Cria uma cópia superficial do atual Object. (Herdado de Object) |
| Release() |
Liberta o SemaphoreSlim objeto uma vez. |
| Release(Int32) |
Liberta o SemaphoreSlim objeto um número especificado de vezes. |
| ToString() |
Devolve uma cadeia que representa o objeto atual. (Herdado de Object) |
| Wait() |
Bloqueia o thread atual até que este possa entrar no SemaphoreSlimarquivo . |
| Wait(CancellationToken) |
Bloqueia o fio atual até que este possa entrar no SemaphoreSlim, enquanto observa um CancellationToken. |
| Wait(Int32, CancellationToken) |
Bloqueia o thread atual até que este possa entrar no SemaphoreSlim, usando um inteiro assinado de 32 bits que especifica o timeout, enquanto observa um CancellationToken. |
| Wait(Int32) |
Bloqueia a thread atual até que esta possa introduzir o SemaphoreSlim, usando um inteiro assinado de 32 bits que especifica o timeout. |
| Wait(TimeSpan, CancellationToken) |
Bloqueia o thread atual até que possa entrar no SemaphoreSlim, usando a TimeSpan que especifica o timeout, enquanto observa um CancellationToken. |
| Wait(TimeSpan) |
Bloqueia o thread atual até que este possa entrar no SemaphoreSlim, usando a TimeSpan para especificar o timeout. |
| WaitAsync() |
Espera assíncronamente para introduzir o SemaphoreSlim. |
| WaitAsync(CancellationToken) |
Aguarda assíncronamente para introduzir o SemaphoreSlim, enquanto observa um CancellationToken. |
| WaitAsync(Int32, CancellationToken) |
Assíncronamente espera para introduzir o SemaphoreSlim, usando um inteiro com sinal de 32 bits para medir o intervalo de tempo, enquanto observa um CancellationToken. |
| WaitAsync(Int32) |
Aguarda assíncronamente para introduzir o SemaphoreSlim, usando um inteiro assinado de 32 bits para medir o intervalo de tempo. |
| WaitAsync(TimeSpan, CancellationToken) |
Assíncronamente espera para introduzir o SemaphoreSlim, usando a TimeSpan para medir o intervalo de tempo, enquanto observa um CancellationToken. |
| WaitAsync(TimeSpan) |
Aguarda assíncronamente para introduzir o SemaphoreSlim, usando a TimeSpan para medir o intervalo de tempo. |
Aplica-se a
Segurança de Thread
Todos os membros públicos e protegidos de SemaphoreSlim são seguros para threads e podem ser usados em simultâneo a partir de múltiplas threads, com exceção de Dispose(), que só deve ser usado quando todas as outras operações no SemaphoreSlim tiverem concluído.