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
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
继承
SemaphoreSlim
属性
实现

示例

下面的示例创建一个信号量,其最大计数为三个线程,初始计数为零个线程。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);
                
                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.

注解

信号量分为两种类型:本地信号量和命名系统信号量。Semaphores are of two types: local semaphores and named system semaphores. 本地信号灯对应用程序而言是本地的,系统信号量在整个操作系统中均可见,适用于进程间同步。Local semaphores are local to an application, system semaphores are visible throughout the operating system and are suitable for inter-process synchronization. SemaphoreSlimSemaphore 不使用 Windows 内核信号量的类的轻型替代项。The 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 或 LIFO。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. 可以从属性获取信号量的计数 CurrentCountThe semaphore's count is available from the CurrentCount property.

重要

SemaphoreSlim类不会对 Wait 、和方法的调用强制执行线程或任务标识 WaitAsync ReleaseThe 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 与方法的调用正确配对 ReleaseIt 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

返回一个可用于在信号量上等待的 WaitHandleReturns 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()

获取当前实例的 TypeGets 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 为止,同时观察 CancellationTokenBlocks 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 位带符号整数来指定超时,同时观察 CancellationTokenBlocks 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 来指定超时,同时观察 CancellationTokenBlocks 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)

在观察 CancellationToken 时,输入 SemaphoreSlim 的异步等待。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)

在观察 CancellationToken 时,输入 SemaphoreSlim 的异步等待,使用 32 位带符号整数度量时间间隔。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.