2010-02-15 46 views
4

我有一個內部使用工作線程的類。目前,ctor啓動線程,dtor停止(並等待)它。這被認爲是很好的代碼?我認爲爲此目的單獨使用start()/stop()函數會更好。ctor/dtor啓動/停止線程或更好地使用start()/ stop()?

其中一個問題是停止並等待線程可能會拋出異常,這在dtor中是不好的。

什麼,你會建議我:

  1. 離開的代碼,因爲它是和正好趕上,並在析構函數
  2. 使用start()/stop()記錄異常,讓客戶端處理異常,只是刪除線程(並在不潔的關機時發出警告或某事)

回答

4

我可能不會在構造函數中啓動線程,而是有一個啓動函數。如果工作者線程基本上對用戶不可見,那麼它可能沒什麼區別,並且從構造函數開始可能會更好。但是,如果用戶以任何方式與工作者線程交互(例如,他們的代碼在其中運行),那麼最終有人需要在創建對象之後但在線程運行之前設置一些狀態。墨菲定律保證它;-)

我會停止它在析構函數中,並捕獲並記錄異常。如果用戶可能需要知道停止的結果(例如,如果失敗意味着工作者線程可能沒有完成其工作),那麼也有一個停止功能,他們可以選擇調用以獲取該信息。

順便說一句,關於在構造函數中啓動線程也有一些技術問題。新線程可能會在構造函數返回到舊線程之前運行。如果訪問它的所有者對象(例如報告結果),則它可以訪問一個不完整構造的對象。這通常很容易解決,直到您從原始類繼承的地步。現在線程在派生類構造函數運行之前啓動,這可能會導致各種麻煩。因此,如果您確實在構造函數中啓動線程,並且線程可以直接或間接訪問該對象,請注意並留下很多警告。

+0

我幾乎可以肯定運行構造函數時,你都保證有一個完全建立對象。調用純虛函數的唯一問題。 –

+0

@aiwarrior:如果基類構造函數啓動一個線程,並且派生類構造函數執行某個動作X,則在新線程中運行的代碼可以在動作X發生之前看到該對象。因此,該對象不是完全構建的。 –

+0

我同意這一點值得一提。仔細閱讀你的確意味着這只是潛力。我很挑剔,因爲只有當繼承是可以期待的時候,它纔是危險的,當然,如果語言允許的話,那麼它是可以預期的。很好的解釋。 –

0

取決於類的語義。如果內部需要一個線程,最好在沒有外界干預的情況下啓動/停止線程。

一個好的事情可能是使用線程池,即重用該類的前一個實例所丟棄的線程。

1

我沒有看到兩個選項是互斥的。這是我想做到這一點:

{ 
    mythread worker1; // starts 
    mythread worker2(false); // doesn't start 
    worker2.start(); 

    worker1.stop(); 

} // dtor. of worker2 stops it, dtor. of worker1 does nothing