首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

淺談 ManualResetEvent 與 AutoResetEvent 的差異

     編輯:關於.NET

.NET 提供兩種事件訊號類別:ManualResetEvent(手動重設)與 AutoResetEvent(自動重設)。兩者皆繼承自 WaitHandle,底層對應 Win32 CreateEvent API,差別僅在第二個參數 bManualReset 為 true 或 false。核心差異在於:訊號狀態被重設為非訊號狀態的時機由誰控制。

生活化類比:樂透開獎

  • 發訊號者:開獎機構(決定中獎號碼)。
  • 傳訊號者:電視媒體(即時轉播)。
  • 等訊號者:彩民(守在螢幕前等結果)。

開獎前皆為「無訊號狀態」(彩民等待);開獎瞬間發出「有訊號」(號碼出爐),彩民得知結果後各自散去(執行續被喚醒)。

ManualResetEvent:手動重設

特性:Set() 後訊號持續保持「有訊號」狀態,直到程式碼明確呼叫 Reset() 才歸零。所有等待的執行緒同時被釋放。

var mre = new ManualResetEvent(false);

// 三個執行緒等待
new Thread(A).Start(); new Thread(B).Start(); new Thread(C).Start();

mre.Set(); // 發訊號:三個執行緒全數喚醒

// 若不呼叫 Reset(),後續新增的執行緒 D 也不會阻塞
new Thread(D).Start(); // 直接跑過 WaitOne()

mre.Reset(); // 手動歸零
new Thread(D).Start(); // 此時會阻塞
mre.Set();             // 再次發訊號喚醒 D

適用場景:單次觸發、多執行緒同步啟動、狀態旗標(如「資料已載入完成」)。

AutoResetEvent:自動重設

特性:Set() 釋放單一等待執行緒(由 OS 排程器決定),隨後立即自動重設為無訊號狀態。其餘執行緒持續阻塞。

var are = new AutoResetEvent(false);

new Thread(A).Start(); new Thread(B).Start(); new Thread(C).Start();

are.Set(); // 僅喚醒 A、B、C 中隨機一個,其餘仍阻塞

// 若在執行緒內再次呼叫 Set(),可喚醒下一個
// 否則需外部再次呼叫 Set()

適用場景:生產者/消費者佇列、互斥存取、逐項任務分派。

關鍵差異對照表

特性ManualResetEventAutoResetEvent
訊號持續時間直到手動 Reset()喚醒一個執行緒後自動歸零
喚醒執行緒數所有等待者僅一個(隨機)
類比大門敞開,所有人可通行單人旋轉門,一人通過即鎖上
典型用途廣播通知、階段性同步資源互斥、工作佇列消費

程式碼驗證建議

文章附上兩個完整 Console 應用程式範例,分別示範 ManualResetEvent 與 AutoResetEvent 的行為差異。建議實際執行觀察輸出順序與阻塞情況,加深體會。

總結

選擇原則簡單:需一次通知多個執行緒、或狀態需持久保持 → ManualResetEvent;需逐個喚醒處理、互斥存取 → AutoResetEvent。理解「誰負責重設訊號」是掌握兩者本質的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved