[C#.NET][Thread] 執行緒同步機制 - AutoResetEvent / ManualResetEvent

[C#.NET][Thread] 執行緒同步機制 - AutoResetEvent / ManualResetEvent

這兩個類別AutoResetEvent 類別ManualResetEvent 類別WaitOne方法可以使執行緒進入Blocks變成WaitSleepJoin狀態,Set方法可以進入Waitting回到Running狀態。

所以我們可以用它們來等候其他的執行緒進而達到資料同步機制,而他們兩個的用法很像,

1.當使用Set方法後AutoResetEvent會自動處於未收到信號的狀態,而ManualResetEvent必須要再呼叫Reset方法後才會處於未收到信號的狀態。

2.AutoResetEventManualResetEvent 是衍生自新的 EventWaitHandle 類別,AutoResetEvent 的功能相等於以 EventResetMode.AutoResetManualResetEvent 的功能等於以 EventResetMode.ManualReset

3.AutoResetEvent 一次只能喚醒一個執行緒,ManualResetEvent可以喚醒多個執行緒

4.ManualResetEvent,使用WaitOne鎖定後,必須要再呼叫Reset方法,使其回到未鎖定狀態;AutoResetEvent 就不必呼叫Reset方法,會自動的回到未鎖定狀態。

 

接下來我們用程式碼來演練觀察其狀態

image

 

按F5來看看,我們可以看到當執行緒進入到ThreadMethod方法並執行第37行的_AutoWait方法後,並沒有往下執行到40行,反而是直接印出第28行的資料,直到執行30行的_AutoWait.Set方法後才有印出40行的訊息,WaitOne的方法確實的鎖定了執行緒,狀態也是WaitSleepJoin。

 

 

image

 

再來一樣利用上段程式碼來觀察,這次來看ManualResetEvent,解開_ManualWait的註解

image

 

果然,被鎖定的執行緒一次全部被喚醒了

image

所以我們可以把EventWaitHandle.WaitOne方法用來當成暫停,EventWaitHandle.Set方法當成繼續,就不要用Thread.Suspend / Thread.Resume這兩個危險的方法了。

 

 

 

 

 

 

 

 

也可以看看MSDN上的例子使用WaitHandle.WaitAll方法來等待所有執行緒完成,用以達到同步機制。

http://msdn.microsoft.com/zh-tw/library/system.threading.manualresetevent.aspx

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo