SemaphoreSlim SemaphoreSlim SemaphoreSlim SemaphoreSlim Class

定義

代表 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
繼承
SemaphoreSlimSemaphoreSlimSemaphoreSlimSemaphoreSlim
屬性
實作

範例

下列範例會建立一個號誌的三個執行緒的最大計數與初始計數為零的執行緒。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. SemaphoreSlim是輕量級替代方案Semaphore不會使用 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. 若要進入號誌,執行緒會呼叫其中一個WaitWaitAsync多載。To 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. 將旗號的計數是可從CurrentCount屬性。The semaphore's count is available from the CurrentCount property.

重要

SemaphoreSlim類別並不會強制呼叫的執行緒或工作身分識別WaitWaitAsync,和Release方法。The 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(Int32) SemaphoreSlim(Int32) 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(Int32, Int32) SemaphoreSlim(Int32, Int32) 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 AvailableWaitHandle AvailableWaitHandle AvailableWaitHandle

傳回可用來等候號誌的 WaitHandleReturns a WaitHandle that can be used to wait on the semaphore.

CurrentCount CurrentCount CurrentCount CurrentCount

取得可以進入 SemaphoreSlim 物件的剩餘執行緒數目。Gets the number of remaining threads that can enter the SemaphoreSlim object.

方法

Dispose() Dispose() Dispose() Dispose()

釋放 SemaphoreSlim 類別目前的執行個體所使用的全部資源。Releases all resources used by the current instance of the SemaphoreSlim class.

Dispose(Boolean) Dispose(Boolean) Dispose(Boolean) Dispose(Boolean)

釋放 SemaphoreSlim 所使用的 Unmanaged 資源,並選擇性釋放 Managed 資源。Releases the unmanaged resources used by the SemaphoreSlim, and optionally releases the managed resources.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

判斷指定的物件是否等於目前的物件。Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode() GetHashCode() GetHashCode() GetHashCode()

做為預設雜湊函式。Serves as the default hash function.

(Inherited from Object)
GetType() GetType() GetType() GetType()

取得目前執行個體的 TypeGets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

建立目前 Object 的淺層複本 (Shallow Copy)。Creates a shallow copy of the current Object.

(Inherited from Object)
Release() Release() Release() Release()

釋出 SemaphoreSlim 物件一次。Releases the SemaphoreSlim object once.

Release(Int32) Release(Int32) Release(Int32) Release(Int32)

釋出 SemaphoreSlim 物件指定的次數。Releases the SemaphoreSlim object a specified number of times.

ToString() ToString() ToString() ToString()

傳回代表目前物件的字串。Returns a string that represents the current object.

(Inherited from Object)
Wait() Wait() Wait() Wait()

執行封鎖目前的執行緒,直到此執行緒可以進入 SemaphoreSlim 為止。Blocks the current thread until it can enter the SemaphoreSlim.

Wait(CancellationToken) Wait(CancellationToken) Wait(CancellationToken) Wait(CancellationToken)

封鎖目前的執行緒,直到此執行緒可以進入 SemaphoreSlim 為止,同時觀察 CancellationTokenBlocks the current thread until it can enter the SemaphoreSlim, while observing a CancellationToken.

Wait(Int32) Wait(Int32) Wait(Int32) 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) Wait(Int32, CancellationToken) Wait(Int32, CancellationToken) 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) Wait(TimeSpan) Wait(TimeSpan) Wait(TimeSpan)

封鎖目前的執行緒,直到此執行緒可以進入 SemaphoreSlim 為止 (使用 TimeSpan 以指定逾時)。Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan to specify the timeout.

Wait(TimeSpan, CancellationToken) Wait(TimeSpan, CancellationToken) Wait(TimeSpan, CancellationToken) 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() WaitAsync() WaitAsync() WaitAsync()

非同步等待進入 SemaphoreSlimAsynchronously waits to enter the SemaphoreSlim.

WaitAsync(CancellationToken) WaitAsync(CancellationToken) WaitAsync(CancellationToken) WaitAsync(CancellationToken)

在觀察 SemaphoreSlim 時,非同步等待進入 CancellationTokenAsynchronously waits to enter the SemaphoreSlim, while observing a CancellationToken.

WaitAsync(Int32) WaitAsync(Int32) WaitAsync(Int32) WaitAsync(Int32)

非同步等待進入 SemaphoreSlim,並使用 32 位元帶正負號的整數來測量時間間隔。Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval.

WaitAsync(Int32, CancellationToken) WaitAsync(Int32, CancellationToken) WaitAsync(Int32, CancellationToken) WaitAsync(Int32, CancellationToken)

在觀察 SemaphoreSlim 時,非同步等待進入 CancellationToken,並使用 32 位元帶正負號的整數來測量時間間隔。Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval, while observing a CancellationToken.

WaitAsync(TimeSpan) WaitAsync(TimeSpan) WaitAsync(TimeSpan) WaitAsync(TimeSpan)

非同步等待進入 SemaphoreSlim,並使用 TimeSpan 來測量時間間隔.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval.

WaitAsync(TimeSpan, CancellationToken) WaitAsync(TimeSpan, CancellationToken) WaitAsync(TimeSpan, CancellationToken) WaitAsync(TimeSpan, CancellationToken)

在觀察 SemaphoreSlim 時,非同步等待進入 TimeSpan,並使用 CancellationToken來測量時間間隔。Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval, while observing a CancellationToken.

適用於

執行緒安全性

所有 public 和 protected 成員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.

另請參閱