SemaphoreSlim Класс

Определение

Представляет упрощенную альтернативу семафору Semaphore, ограничивающему количество потоков, которые могут параллельно обращаться к ресурсу или пулу ресурсов.Represents a lightweight alternative to Semaphore that limits the number of threads that can access a resource or pool of resources concurrently.

public ref class SemaphoreSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class SemaphoreSlim : IDisposable
type SemaphoreSlim = class
    interface IDisposable
Public Class SemaphoreSlim
Implements IDisposable
Наследование
SemaphoreSlim
Атрибуты
Реализации

Примеры

В следующем примере создается семафор с максимальным числом трех потоков и начальным числом 0 потоков.The following example creates a semaphore with a maximum count of three threads and an initial count of zero threads. В примере запускается пять задач, все из которых блок ожидает семафор.The example starts five tasks, all of which block waiting for the semaphore. Главный поток вызывает Release(Int32) перегрузку, чтобы увеличить число семафоров до максимального значения, что позволяет трем задачам войти в семафор.The main thread calls the Release(Int32) overload to increase the semaphore count to its maximum, which allows three tasks to enter the semaphore. При каждом освобождении семафора отображается предыдущее число семафоров.Each time the semaphore is released, the previous semaphore count is displayed. Сообщения консоли записывают использование семафора.Console messages track semaphore use. Рабочий интервал смоделированной работы немного увеличивается для каждого потока, чтобы упростить чтение выходных данных.The simulated work interval is increased slightly for each thread to make the output easier to read.

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);
            semaphore.Wait();

            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);

            Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.",
                              Task.CurrentId, semaphore.Release()); } );
        }

        // 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.

Комментарии

Семафоры имеют два типа: локальные семафоры и именованные системные семафоры.Semaphores are of two types: local semaphores and named system semaphores. Первый является локальным для приложения.The former is local to an app. Последний является видимым во всей операционной системе и подходит для синхронизации между процессами.The latter is visible throughout the operating system and is suitable for inter-process synchronization. Является упрощенной альтернативой Semaphore классу, который не использует семафоры ядра Windows. SemaphoreSlimThe SemaphoreSlim is a lightweight alternative to the Semaphore class that doesn't use Windows kernel semaphores. Semaphore ВSemaphoreSlim отличие от класса, класс не поддерживает именованные системные семафоры.Unlike the Semaphore class, the SemaphoreSlim class doesn't support named system semaphores. Его можно использовать только в качестве локального семафора.You can use it as a local semaphore only. SemaphoreSlim Класс является рекомендуемым семафором для синхронизации в рамках одного приложения.The SemaphoreSlim class is the recommended semaphore for synchronization within a single app.

Упрощенный семафор управляет доступом к пулу ресурсов, которые являются локальными для вашего приложения.A lightweight semaphore controls access to a pool of resources that is local to your application. При создании экземпляра семафора можно указать максимальное число потоков, которые могут одновременно входить в семафор.When you instantiate a semaphore, you can specify the maximum number of threads that can enter the semaphore concurrently. Вы также указываете начальное число потоков, которые могут одновременно входить в семафор.You also specify the initial number of threads that can enter the semaphore concurrently. Определяет число семафоров.This defines the semaphore's count.

Счетчик уменьшается каждый раз, когда поток входит в семафор, и увеличивается каждый раз, когда поток освобождает семафор.The count is decremented each time a thread enters the semaphore, and incremented each time a thread releases the semaphore. Чтобы ввести семафор, поток вызывает одну из Wait перегрузок или. WaitAsyncTo enter the semaphore, a thread calls one of the Wait or WaitAsync overloads. Чтобы освободить семафор, он вызывает одну из Release перегрузок.To release the semaphore, it calls one of the Release overloads. Если счетчик достигнет нуля, последующие вызовы одного из Wait методов будут блокироваться до освобождения семафора другими потоками.When the count reaches zero, subsequent calls to one of the Wait methods block until other threads release the semaphore. Если заблокировано несколько потоков, то нет гарантированного порядка, такого как FIFO или ЛИФО, которые определяют, когда потоки вводят семафор.If multiple threads are blocked, there is no guaranteed order, such as FIFO or LIFO, that controls when threads enter the semaphore.

Базовая структура кода, использующего семафор для защиты ресурсов,:The basic structure for code that uses a semaphore to protect resources is:

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

Когда семафор освобожден всеми потоками, счетчик будет иметь максимальное значение, указанное при создании семафора.When all threads have released the semaphore, the count is at the maximum value specified when the semaphore was created. Счетчик семафора доступен из CurrentCount свойства.The semaphore's count is available from the CurrentCount property.

Важно!

Класс не применяет удостоверение потока или задачи к вызовам WaitAsync Waitметодов, Release и. SemaphoreSlimThe SemaphoreSlim class doesn't enforce thread or task identity on calls to the Wait, WaitAsync, and Release methods. Кроме того, если SemaphoreSlim(Int32) конструктор используется для создания экземпляра SemaphoreSlim объекта, CurrentCount свойство может увеличиваться за пределами значения, установленного конструктором.In addition, if the SemaphoreSlim(Int32) constructor is used to instantiate the SemaphoreSlim object, the CurrentCount property can increase beyond the value set by the constructor. Программист следит за тем, чтобы вызовы Wait методов или WaitAsync были Release парными с вызовами методов.It is the programmer's responsibility to ensure that calls to Wait or WaitAsync methods are appropriately paired with calls to Release methods.

Конструкторы

SemaphoreSlim(Int32)

Инициализирует новый экземпляр класса SemaphoreSlim, указывая первоначальное число запросов, которые могут выполняться одновременно.Initializes a new instance of the SemaphoreSlim class, specifying the initial number of requests that can be granted concurrently.

SemaphoreSlim(Int32, Int32)

Инициализирует новый экземпляр класса SemaphoreSlim, указывая изначальное и максимальное число запросов, которые могут выполняться одновременно.Initializes a new instance of the SemaphoreSlim class, specifying the initial and maximum number of requests that can be granted concurrently.

Свойства

AvailableWaitHandle

Возвращает дескриптор WaitHandle, который может использоваться для ожидания семафора.Returns a WaitHandle that can be used to wait on the semaphore.

CurrentCount

Возвращает количество оставшихся потоков, которым разрешено входить в объект SemaphoreSlim.Gets the number of remaining threads that can enter the SemaphoreSlim object.

Методы

Dispose()

Освобождает все ресурсы, используемые текущим экземпляром класса SemaphoreSlim.Releases all resources used by the current instance of the SemaphoreSlim class.

Dispose(Boolean)

Освобождает неуправляемые ресурсы, используемые журналом SemaphoreSlim, и при необходимости освобождает также управляемые ресурсы.Releases the unmanaged resources used by the SemaphoreSlim, and optionally releases the managed resources.

Equals(Object)

Определяет, равен ли заданный объект текущему объекту.Determines whether the specified object is equal to the current object.

(Унаследовано от Object)
GetHashCode()

Служит хэш-функцией по умолчанию.Serves as the default hash function.

(Унаследовано от Object)
GetType()

Возвращает объект Type для текущего экземпляра.Gets the Type of the current instance.

(Унаследовано от Object)
MemberwiseClone()

Создает неполную копию текущего объекта Object.Creates a shallow copy of the current Object.

(Унаследовано от Object)
Release()

Освобождает объект SemaphoreSlim один раз.Releases the SemaphoreSlim object once.

Release(Int32)

Освобождает объект SemaphoreSlim указанное число раз.Releases the SemaphoreSlim object a specified number of times.

ToString()

Возвращает строку, представляющую текущий объект.Returns a string that represents the current object.

(Унаследовано от Object)
Wait()

Блокирует текущий поток, пока он не сможет войти в SemaphoreSlim.Blocks the current thread until it can enter the SemaphoreSlim.

Wait(CancellationToken)

Блокирует текущий поток до тех пор, пока он не сможет войти в SemaphoreSlim. Кроме того, метод контролирует токен CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, while observing a CancellationToken.

Wait(Int32)

Блокирует текущий поток до тех пор, пока он не сможет войти в SemaphoreSlim, используя 32-разрядное знаковое целое число, которое определяет время ожидания.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout.

Wait(Int32, CancellationToken)

Блокирует текущий поток до тех пор, пока он не сможет войти в SemaphoreSlim, используя 32-разрядное знаковое целое число, которое определяет время ожидания. Кроме того, метод контролирует токен CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout, while observing a CancellationToken.

Wait(TimeSpan)

Блокирует текущий поток до тех пор, пока он не сможет войти в SemaphoreSlim, используя значение TimeSpan для определения времени ожидания.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan to specify the timeout.

Wait(TimeSpan, CancellationToken)

Блокирует текущий поток до тех пор, пока он не сможет войти в SemaphoreSlim, используя значение TimeSpan, которое определяет время ожидания. Кроме того, метод контролирует токен CancellationToken.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan that specifies the timeout, while observing a CancellationToken.

WaitAsync()

Асинхронно ожидает входа в SemaphoreSlim.Asynchronously waits to enter the SemaphoreSlim.

WaitAsync(CancellationToken)

Асинхронно ожидает входа в SemaphoreSlim, соблюдая CancellationToken.Asynchronously waits to enter the SemaphoreSlim, while observing a CancellationToken.

WaitAsync(Int32)

Асинхронно ожидает входа в SemaphoreSlim, используя 32битовое целое число со знаком для измерения интервала времени.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval.

WaitAsync(Int32, CancellationToken)

Асинхронно ожидает входа в SemaphoreSlim, используя 32битовое целое число со знаком для измерения интервала времени, соблюдая CancellationToken.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval, while observing a CancellationToken.

WaitAsync(TimeSpan)

Асинхронно ожидает входа в SemaphoreSlim, используя TimeSpan для измерения интервала времени.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval.

WaitAsync(TimeSpan, CancellationToken)

Асинхронно ожидает входа в SemaphoreSlim, используяTimeSpan для измерения интервала времени, соблюдая CancellationToken.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval, while observing a CancellationToken.

Применяется к

Потокобезопасность

Все открытые и защищенные члены SemaphoreSlim являются потокобезопасными и могут использоваться одновременно из нескольких потоков, за Dispose()исключением, которое должно использоваться только после завершения SemaphoreSlim всех остальных операций в.All public and protected members of SemaphoreSlim are thread-safe and may be used concurrently from multiple threads, with the exception of Dispose(), which must be used only when all other operations on the SemaphoreSlim have completed.

Дополнительно