2010-03-08 209 views
6

我打算使用自動重置事件句柄來進行線程間通信。.NET線程同步

EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset); 

我的生產者線程的代碼看起來像下面

produceSomething(); 
handle.Set(); 

在消費者線程,我要下載的數據每隔一分鐘或當製片 被稱爲設置方法

try 
{ 
    while(true) 
    { 
     handle.WaitOne(60000, false); 
     doSomething(); // Downloads data from Internet. 
         // Takes lot of time to complete it. 
    } 
} 
catch(ThreadAbortException) 
{ 
    cleanup(); 
} 

我的問題是,如果消費者線程正在運行doSomething函數和生產者調用設置函數,自動重置事件對象的狀態是什麼?

我的要求是儘快生產者調用設置方法我必須從互聯網上下載新的數據。如果doSomething函數正在運行,當Producer調用set方法時,我必須中斷它並再次調用。

回答

2

自動重置事件就像在第一個線程通過後關閉的門。如果在一個或多個線程正在等待時設置它,則一個線程會醒來,然後事件被重置,其餘線程繼續等待。

如果設置時沒有線程正在等待,然後調用handle.WaitOne第一個線程不會等待,但它會導致事件被重置,然後繼續。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

呼叫設置信號的AutoResetEvent釋放等待線程。 AutoResetEvent保持發送狀態,直到釋放一個等待線程,然後自動返回到非信號狀態。如果沒有線程在等待,狀態將無限期地發送。

如果一個線程在AutoResetEvent處於信號狀態時調用WaitOne,則線程不會阻塞。 AutoResetEvent立即釋放該線程並返回到非信號狀態。

1

在您的方案中自動重置事件的問題是「設置」它不支持排隊。

也就是說,設置一個自動重置事件允許一個線程進入,如果您在任何線程「消耗」您的事件之前再次設置它,那麼「set」將會丟失。你可能期望兩個線程能夠進入並消費你所生產的任何東西,但事實上只有一個線程能夠做到這一點。

就你而言,如果你生產的速度比你消費的更快,那麼自動重置事件可能會引起誤解。想象一下這種情況。

  • 生產者生產一個項目。
  • 消費者消費該物品(重置事件並開始從INET下載)
  • 生產者生產第二個物品。
  • 生產者生產第三個項目。
  • 產品停止。
  • 消費者消費第二個項目(重新設定事件並重新開始下載)
  • 由於自動重置事件已被重置,消費者將不會獲得第三個項目。