類別 System.Threading.Semaphore 代表具名 (systemwide) 或本機號誌。 它是 Win32 號誌物件周圍的精簡包裝函式。 Win32 信號量是計數信號量,可用來控制對資源池的存取。
類別 SemaphoreSlim 代表輕量型快速號誌,可在預期等候時間非常短時,用於在單一程式中等候。 SemaphoreSlim 盡可能依賴 Common Language Runtime (CLR) 所提供的同步處理基本類型。 不過,它也會視需要提供延遲初始化的核心型等候句柄,以支援等候多個旗號。 SemaphoreSlim 也支援使用取消令牌,但它不支援具名旗號或使用等候句柄進行同步處理。
管理有限的資源
線程會藉由呼叫來自WaitOne類別的WaitHandle方法進入旗號。在System.Threading.Semaphore物件的情況下,或是呼叫在SemaphoreSlim.Wait物件中繼承的SemaphoreSlim.WaitAsync或SemaphoreSlim方法。 當呼叫傳回時,信號上的計數會遞減。 當執行緒請求進入且計數為零時,執行緒會阻塞。 當線程藉由呼叫 Semaphore.Release 或 SemaphoreSlim.Release 方法釋放旗號時,允許封鎖的線程輸入。 沒有保證的順序,例如先入先出(FIFO)或後入先出(LIFO),阻塞的線程進入信號量。
線程可以重複呼叫 System.Threading.Semaphore 物件的 WaitOne 方法或 SemaphoreSlim 物件的 Wait 方法,多次進入號誌。 若要釋放旗號,線程可以呼叫 Semaphore.Release() 或 SemaphoreSlim.Release() 方法多載相同的次數,或呼叫 Semaphore.Release(Int32) 或 SemaphoreSlim.Release(Int32) 方法多載,並指定要釋放的項目數目。
旗號和線程身分識別
這兩種信號量類型不會在方法 WaitOne、Wait、Release 和 SemaphoreSlim.Release 的呼叫上強加線程識別。 例如,信號的常見使用案例牽涉到生產者線程和取用者線程,其中一個線程一律遞增旗號計數,另一個線程一律遞減。
程序設計人員有責任確保線程不會釋放信號太多次。 例如,假設信號的最大計數為 2,而執行緒 A 和執行緒 B 都已經進入信號。 如果線程 B 中的程式設計錯誤導致呼叫 Release
兩次,這兩個呼叫都會成功。 號誌上的計數已滿,當執行緒 A 最終呼叫 Release
時,會拋出 SemaphoreFullException。
具名號誌
Windows作業系統允許信號具有名稱。 具名信號量是系統範圍的。 也就是說,一旦建立具名旗號,所有進程中的所有線程都會看見它。 因此,具名信號量可用來同步程序和線程的活動。
您可以使用其中一個指定名稱的建構函式,建立 Semaphore 代表具名系統旗號的物件。
備註
因為具名旗號是全系統範圍,所以可以有多個 Semaphore 物件代表相同的具名旗號。 每次呼叫建構函式或 Semaphore.OpenExisting 方法時,都會建立新的 Semaphore 物件。 指定相同名稱會重複建立多個代表相同具名旗號的物件。
當您使用具名旗號時,請小心。 因為它們在整個系統中廣泛使用,所以使用相同名稱的另一個進程可能會意外地闖入您的信號量。 在同一部計算機上執行的惡意代碼可以使用此程式代碼作為阻斷服務攻擊的基礎。
使用訪問控制安全性來保護 Semaphore 代表具名號誌的物件,最好是使用指定 System.Security.AccessControl.SemaphoreSecurity 物件的建構函式。 您也可以使用 Semaphore.SetAccessControl 方法來套用訪問控制安全性,但這會在信號量建立和受到保護之間留下漏洞時間窗口。 使用訪問控制安全性保護旗號有助於防止惡意攻擊,但無法解決意外名稱衝突的問題。