2015-05-02 28 views
5

我有一個Windows服務,它在單獨的線程上產生一組子活動,並且只應在所有這些活動都成功完成時終止。我不知道在收到停止信號後終止一個活動需要多長時間。在OnStop()期間,我會等待該停止信號的間隔,並且只要系統願意授予它,就會繼續請求額外的時間。什麼是RequestAdditionalTime()的安全開銷?

這裏的基本結構:

class MyService : ServiceBase 
{ 
    private CancellationTokenSource stopAllActivities; 
    private CountdownEvent runningActivities; 

    protected override void OnStart(string[] args) 
    { 
     // ... start a set of activities that signal runningActivities 
     //  when they stop 
     // ... initialize runningActivities to the number of activities 
    } 

    protected override void OnStop() 
    { 
     stopAllActivities.Cancel(); 

     while (!runningActivities.Wait(10000)) 
     { 
      RequestAdditionalTime(15000); // NOTE: 5000 added for overhead 
     } 
    } 
} 

到底有多少「開銷」我應該在RequestAdditionalTime呼叫加入?我擔心這些請求是累積的,而不是基於每次撥打RequestAdditionalTime時的時間點。如果是這種情況,增加開銷可能會導致系統最終拒絕請求,因爲它將來會太遠。但是如果我不添加任何開銷,那麼我的服務可能會在它有機會請求下一塊額外時間之前終止。

回答

5

This post不完全是令人鼓舞的:

MSDN文檔中沒有提到這一點,但它出現在RequestAdditionalTime指定的值實際上不是「額外」的時間。相反,它會替換ServicesPipeTimeout中的值。更糟糕的是,任何大於兩分鐘(120000毫秒)的值都會被忽略,即在兩分鐘內上限。

我希望情況並非如此,但我將此作爲最糟糕的答案發布。

更新:該文章的作者非常友好,可以發表非常詳細的回覆我的評論,我已經在下面複製。

拉爾斯,簡短的回答是否定的。

我想說的是,現在我意識到Windows服務應該被設計爲在需要時快速啓動和終止處理。作爲開發人員,我們傾向於專注於處理的實現,然後將其打包並作爲Windows服務提供。

但是,這確實不是設計Windows服務的正確方法。服務必須能夠快速響應請求,以便不僅在管理員從服務控制檯發出請求時啓動和停止,而且在操作系統正在請求啓動作爲其啓動處理的一部分或由於它正在關閉而停止時,

請考慮當Windows配置爲在UPS發出電源故障時關閉時發生的情況。該服務不適合以「我需要幾分鐘......」來回應。

即使在執行長時間運行的處理任務時,也可以編寫能夠快速響應的服務來停止請求。通常,長時間運行的過程將由數據的批處理組成,並且處理應該檢查是否在確保數據一致性的最小工作單元級別上請求了停止。

舉個例子,我發現停止超時的第一個服務是一個涉及處理遠程服務器上的通知隊列的問題。處理從隊列中檢索通知,調用Web服務以檢索與通知主題相關的數據,然後寫入數據文件以供其他應用程序處理。

我實現了處理作爲一個計時器驅動調用一個單一的方法。一旦該方法被調用,它將不會返回,直到隊列中的所有通知都被處理完畢。我意識到這是Windows服務的錯誤,因爲偶爾會有成千上萬的通知在隊列中,處理可能需要幾分鐘的時間。

該方法能夠處理每秒50個通知。所以,我應該做的是在處理每個通知之前執行一次檢查以查看是否已請求停止。這將允許該方法在完成通知處理但在開始處理下一個通知之前返回。這可以確保服務能夠快速響應停止請求,並且在重新啓動服務時任何待處理的通知仍然排隊等待處理。