SemaphoreSlim 類別

定義

代表 Semaphore 的輕量型替代品,限制可同時存取一項資源或資源集區的執行緒數目。

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
屬性
實作

範例

下列範例會建立最大計數為三個執行緒和零個執行緒的初始計數的號志。 此範例會啟動五個工作,全部都封鎖等候號志。 主執行緒會 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是類別的輕量型替代方案 Semaphore ,不會使用Windows核心旗號。 不同于 類別 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 不會對 、 WaitAsyncRelease 方法的呼叫 Wait 強制執行執行緒或工作識別。 此外,如果使用建 SemaphoreSlim(Int32) 構函式來具現化 SemaphoreSlim 物件, CurrentCount 屬性可能會增加超過建構函式所設定的值。 程式設計人員必須負責確保呼叫 WaitWaitAsync 方法與方法的呼叫 Release 適當配對。

建構函式

SemaphoreSlim(Int32)

指定可同時授與的初始要求數目,初始化 SemaphoreSlim 類別的新執行個體。

SemaphoreSlim(Int32, Int32)

指定可同時授與的初始要求數目及最大數目,初始化 SemaphoreSlim 類別的新執行個體。

屬性

AvailableWaitHandle

傳回可用來等候號誌的 WaitHandle

CurrentCount

取得可以進入 SemaphoreSlim 物件的剩餘執行緒數目。

方法

Dispose()

釋放 SemaphoreSlim 類別目前的執行個體所使用的全部資源。

Dispose(Boolean)

釋放 SemaphoreSlim 所使用的 Unmanaged 資源,並選擇性釋放 Managed 資源。

Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetType()

取得目前執行個體的 Type

(繼承來源 Object)
MemberwiseClone()

建立目前 Object 的淺層複製。

(繼承來源 Object)
Release()

釋出 SemaphoreSlim 物件一次。

Release(Int32)

釋出 SemaphoreSlim 物件指定的次數。

ToString()

傳回代表目前物件的字串。

(繼承來源 Object)
Wait()

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止。

Wait(CancellationToken)

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止,同時觀察 CancellationToken

Wait(Int32)

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止,並使用 32 位元帶正負號的整數來指定逾時。

Wait(Int32, CancellationToken)

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止,並使用 32 位元帶正負號的整數來指定逾時,同時觀察 CancellationToken

Wait(TimeSpan)

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止,並使用 TimeSpan 來指定逾時。

Wait(TimeSpan, CancellationToken)

封鎖目前的執行緒,直到這個執行緒可以進入 SemaphoreSlim 為止,並使用 TimeSpan 來指定逾時,同時觀察 CancellationToken

WaitAsync()

以非同步方式等候進入 SemaphoreSlim

WaitAsync(CancellationToken)

以非同步方式等候進入 SemaphoreSlim,同時觀察 CancellationToken

WaitAsync(Int32)

以非同步方式等候進入 SemaphoreSlim,並使用 32 位元帶正負號的整數來測量時間間隔。

WaitAsync(Int32, CancellationToken)

以非同步方式等候進入 SemaphoreSlim,並使用 32 位元帶正負號的整數來測量時間間隔,同時觀察 CancellationToken

WaitAsync(TimeSpan)

以非同步方式等候進入 SemaphoreSlim,並使用 TimeSpan 來測量時間間隔。

WaitAsync(TimeSpan, CancellationToken)

以非同步方式等候進入 SemaphoreSlim,並使用 TimeSpan 來測量時間間隔,同時觀察 CancellationToken

適用於

執行緒安全性

的所有公用和受保護成員 SemaphoreSlim 都是安全線程,而且可以從多個執行緒同時使用,但例外狀況是 ,只有在 Dispose() 上所有其他作業 SemaphoreSlim 都已完成時,才必須使用。

另請參閱