SemaphoreSlim 类 
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
对可同时访问资源或资源池的线程数加以限制的 Semaphore 的轻量替代。
public ref class SemaphoreSlim : IDisposablepublic class SemaphoreSlim : IDisposable[System.Runtime.InteropServices.ComVisible(false)]
public class SemaphoreSlim : IDisposabletype SemaphoreSlim = class
    interface IDisposable[<System.Runtime.InteropServices.ComVisible(false)>]
type SemaphoreSlim = class
    interface IDisposablePublic Class SemaphoreSlim
Implements IDisposable- 继承
- 
				SemaphoreSlim
- 属性
- 实现
示例
以下示例创建一个信号灯,最大计数为三个线程,初始计数为零个线程。 该示例启动五个任务,所有这些任务都阻止等待信号灯。 主线程调用 Release(Int32) 重载以将信号灯计数增加到其最大值,这允许三个任务进入信号灯。 每次释放信号灯时,都会显示以前的信号灯计数。 控制台消息跟踪信号灯的使用。 每个线程的模拟工作间隔略有增加,以使输出更易于读取。
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.
注解
信号灯有两种类型:本地信号灯和命名系统信号灯。 本地信号灯是应用程序的本地信号量,系统信号量在整个操作系统中可见,适合进程间同步。 这是SemaphoreSlim不使用内核信号量Windows类的轻型替代Semaphore方法。 与类 Semaphore 不同,该 SemaphoreSlim 类不支持命名的系统信号灯。 只能将其用作本地信号灯。 类 SemaphoreSlim 是建议在单个应用中同步的信号灯。
轻型信号灯控制对应用程序本地资源的池的访问。 实例化信号灯时,可以指定可以同时输入信号灯的最大线程数。 还可以指定可以同时输入信号量的初始线程数。 这定义了信号灯的计数。
每次线程进入信号灯时,计数都会递减,每次线程释放信号灯时递增。 若要输入信号灯,线程会调用其中一个 Wait 或 WaitAsync 重载。 若要释放信号灯,它会调用其中一个 Release 重载。 当计数达到零时,对其中一 Wait 个方法的后续调用会阻止,直到其他线程释放信号灯。 如果阻止了多个线程,则无法保证顺序(例如 FIFO 或 LIFO),用于控制线程何时进入信号灯。
使用信号灯保护资源的代码的基本结构是:
' Enter semaphore by calling one of the Wait or WaitAsync methods.
SemaphoreSlim.Wait()
'
' Execute code protected by the semaphore.
'
SemaphoreSlim.Release()
当所有线程都释放信号灯时,计数处于创建信号灯时指定的最大值。 信号灯的计数可从 CurrentCount 属性获取。
重要
类SemaphoreSlim不会对调用WaitWaitAsyncRelease和方法强制实施线程或任务标识。 此外,如果 SemaphoreSlim(Int32) 构造函数用于实例化 SemaphoreSlim 对象,则 CurrentCount 属性可以超出构造函数设置的值。 程序员有责任确保对 Wait 方法的调用或 WaitAsync 方法的调用与调用 Release 正确配对。
构造函数
| SemaphoreSlim(Int32) | 初始化 SemaphoreSlim 类的新实例,以指定可同时授予的请求的初始数量。 | 
| SemaphoreSlim(Int32, Int32) | 初始化 SemaphoreSlim 类的新实例,同时指定可同时授予的请求的初始数量和最大数量。 | 
属性
| AvailableWaitHandle | 返回一个可用于在信号量上等待的 WaitHandle。 | 
| CurrentCount | 获取可以输入 SemaphoreSlim 对象的剩余线程数。 | 
方法
适用于
线程安全性
所有公共成员和受保护的成员 SemaphoreSlim 都是线程安全的,并且可能同时从多个线程使用,但例外,只有在 Dispose()已完成所有其他操作 SemaphoreSlim 时才使用。