2009-11-07 45 views
3

假情況:有一個班級(比方說BackgroundMagic),它有Start()Stop()方法。此類中的工作由單個線程完成,並且每X毫秒只是一個短循環。保持線程空閒或殺死它們/重新啓動它們?

就管理停止/啓動而言,哪個選項更好?無法決定走哪條路。

  1. 第一次調用Start()時,使用IsBackground = true初始化並啓動線程。 使用一個簡單的布爾標誌來指示每個循環周圍是否應該實際做任何工作,或者只是睡覺。初始化初始化後,讓Stop()和Start()簡單地控制布爾標誌。由於IsBackground =應用程序退出時,該線程將被運行時停止並清除。
  2. 強行中止/加入/中斷/停止上的任何內容,並在Start()上再次重新創建線程,而不是讓線程四處閒逛。

...或者更好/更乾淨的方法來做到這一點?

回答

1

創建線程相當昂貴,因此標準的「工業強度」方法是使用標誌來控制線程。對於同一想法的更大規模的變體,考慮線程池,例如Apache使用管理成千上萬的線程,而沒有很多明確的狀態或痛苦的性能影響。

因此,在抽象中,我會爲您的選項#1投票。但如果性能不是問題,並且選項#2的代碼更容易推理,那就去做吧。

0

您還可以使用布爾標誌來指示線程是否應該停止。它給你你的中斷和停止代碼。所以如果有工作和停止循環的話,那麼兩個bools。

您可以考慮的另一件事是使用Dispose模式並在處理對象時清理線程。

0

我會使用bool標誌,但您需要確保它是正確鎖定的或者只能從一個線程設置。你的循環應該是這樣的

while (true) 
{ 
    if (shouldSleep) 
{ 
    Thread.Sleep(interval); 
    continue; 
} 

    doSomeWork(); 

if (shouldCancel) 
{ 
    CleanUpResources(); 
    break; 
} 
} 

這可以確保你能正確地發送線程睡覺,但也終止它。殺死一個線程從來不是一個好主意,因爲線程沒有機會清理使用的任何資源。你需要決定一個合適的睡眠時間間隔。它將確定你的線程需要啓動的延遲。

第二個選項相當昂貴,線程創建涉及一些操作系統資源,啓動時間也相當可觀。如果線程娛樂不會經常發生,並且執行的工作量足夠大,這將是合理的。您可以避免循環方法中涉及的複雜性。

1

互斥或信號量會比簡單的布爾標誌更好,因爲它不需要重複檢查標誌的狀態。簡單地阻塞互斥體/信號量,當你想讓線程運行時,釋放互斥體/信號量,線程將運行一次。

1

線程池不適合長時間運行的任務。線程池非常適用於線程創建開銷大大增加操作開銷的短任務。 .NET 4框架中的TPL(Task Paralell Library)也是如此。

使用專門做這項工作的線程可能是一個好主意,但如何管理它可能是一件大事。如果您在檢查工作之間簡單地執行Thread.Sleep,那麼效率就會降低,因爲現在您無法正常旋轉線程。這稱爲自旋鎖(種類),並且只有在知道您正在等待的資源將很快釋放鎖時纔有效。使用AutoResetEvent會更好。這樣,線程只會被喚醒,因爲生產者線程表示有工作要做。這樣做的好處是不會浪費CPU資源來安排線程,如果沒有任何事情做,並且它允許生產者和消費者之間更少的延遲。

要直接回答您的問題,是的,您可以使用某種bool正常關閉該線程(但我會將其標記爲volatile)。這比中止線程好多了!

參見:

相關問題