假設我正在處理來自多個線程的大量輸入數據。當滿足某些標準時,我可能希望將這些數據作爲特定操作的觸發器。但是,這個行爲並不是可重入的;所以連續兩次觸發同一觸發器應該只導致一次運行。AutoResetEvent類型是原子開關的適當選擇嗎?
使用簡單的bool
標誌來指示操作當前是否正在運行不是一個可靠的解決方案,因爲競爭條件可能會發生,並且兩個(或更多)線程仍可能最終同時運行同一操作。當然,同步對象上的lock
語句中的bool
將起作用;但我通常寧願儘可能避免鎖定*。
目前我在這些情況下做的是使用AutoResetEvent
作爲原子切換的一種形式。該代碼通常看起來是這樣的:
if (conditionMet && readyForAction.WaitOne(0))
{
try
{
doAction();
}
finally
{
readyForAction.Set();
}
}
這工作,但是這讓我感到這可能是一個低於理想的使用情況爲AutoResetEvent
類。你會說這是解決這個問題的適當方法,還是使用其他機制會更有意義?
更新:作爲Jon pointed out,使用Monitor.TryEnter
作爲鎖定策略(而不是簡單lock
,我相信這是大致相當於Monitor.Enter
),真的是相當簡單:
if (conditionMet && Monitor.TryEnter(lockObject))
{
try
{
doAction();
}
finally
{
Monitor.Exit(lockObject);
}
}
那說,我強烈傾向於使用Interlocked
的Henk's idea。這看起來很簡單。
.NET的哪個版本? .NET 4有許多新的並行功能可能會有所幫助。例如http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx – 2010-09-09 07:15:59