2013-11-15 70 views
1

我寫了一個小的Windows服務,它定期執行一項任務。它似乎工作正常,但我有一個問題。在.net Windows服務中處理死工作線程的最佳實踐?

OnStart方法啓動一個「工作線程」,負責執行任務,等待間隔過去並重復該任務。

在「管理工具」的「Windows服務」部分,可以對其進行設置,以便服務在失敗時自動重新啓動。

但是,在工作線程拋出異常的情況下,該服務似乎會繼續運行。我認爲,如果工作線程拋出異常,應該將該服務視爲停止,並且Windows應該採用在服務設置中指定的例外。

完成此操作的最佳實踐是什麼?

+0

假設第在我希望服務在工作者線程死亡時停止,我該怎麼做? –

+0

相關:[可以用.NET編寫的服務自行終止嗎?](http://stackoverflow.com/q/554276/945456) –

回答

1

在我們的例子中,我們不希望單個任務崩潰服務(因爲可能它只是壞的數據,所有其他任務都可以正常完成),所以我們只需將所有工作邏輯封裝在try/catch中,記錄我們遇到的任何異常。我確實有一些異常跟蹤代碼,如果它始終發生故障(例如,網絡或數據庫關閉),則會關閉該服務。但是,如果你的服務只執行一個單獨的任務,並且它的失敗是很好的原因,因此我會停止,那麼我相信編寫代碼來將異常封送回主線程是可行的。當您啓動服務時,您可以保存SynchronizationContext.Current,並在遇到異常時使用它返回主線程。我相信這是停止(恩惠,崩潰)的服務。如果代碼不正確,請原諒代碼。目前我沒有VS在我面前。

void OnStart() 
{ 
    _mainThread = SynchronizationContext.Current(); 
} 

void DoWork() 
{ 
    try 
    { 
    // Do the stuff... 
    } 
    catch (Exception e) 
    { 
    _mainThread.Post(() => Throw); 
    } 
} 

編輯:

關於第二個想法,我想你可以完成你想要的是這樣的...簡單的:)

(Editted在從Ishmaeel意見建議使用Environment.Exit代替Stop

void DoWork() 
{ 
    try 
    { 
    // Do the stuff... 
    } 
    catch (Exception e) 
    { 
    LogException(e); 
    Environment.Exit(1); 
    } 
} 
+0

我沒有很多多線程經驗。你能解釋一下SynchronizationContext在這種情況下的工作原理嗎?另外,我認爲主線程在工作線程啓動後退出,還是我誤會了? –

+0

我還沒有完全掌握它,所以我恐怕我不能完全向你解釋它,而且我也不確定這些線程。我善於從UI界獲取知識並將其應用於服務。請參閱編輯另一個(更簡單)的想法。 –

+1

_RE:第二個想法:_實際上,從服務本身調用「Stop」不是一個好主意**。該方法意味着被Windows的服務管理器調用。該服務不會真的停止,它會遇到額外的'ThreadAbortException'並進入丹尼爾試圖避免的那個幽靈狀態。強制執行異常的崩潰將使得可以利用服務恢復選項需要'Environment.Exit'。 – Ishmaeel