2012-11-19 100 views
1

我有一個用VS 2010/.NET 4.0編寫的windows服務。如何正確停止單線程窗口服務(onStop)?

該服務遵循以下代碼片段的方案:使用計時器,它每隔幾分鐘執行一次所需的行爲。每隔幾分鐘執行一次「所需行爲」的要求現在已經發展成爲大約需要10秒的工作。

我只需要該服務中的單個線程,沒有理由創建多個線程,這就是爲什麼我將windows服務稱爲單線程。

我擔心的是,如果有人通過管理控制檯停止服務,那可能就是服務偶爾會在10秒內完成的工作。

我已經完成了一些關於如何停止服務的閱讀,但有點丟失。有時創建WorkerThreads,有時創建ManualResetEvents,但到目前爲止,我無法完全理解我的Windows服務的最佳發展方向。

我在想,我需要在執行10秒內檢查某種標誌,然後只有在該標誌不告訴我應該停止時才繼續。在onStop方法中,我可能需要等待處理完成。

對於這個理論來說非常重要;)但是我認爲最好的方法是什麼呢,同時考慮下面的代碼片段?

謝謝大家!

Public Class MyService 
    Public _timer As System.Timers.Timer 

    Protected Overrides Sub OnStart(ByVal args() As String) 
     _timer = New System.Timers.Timer() 
     'more timer settings 
     AddHandler _timer.Elapsed, AddressOf _timer_Tick 
     _timer.Start() 
    End Sub 

    Protected Overrides Sub OnStop() 
    ' ???????????????????????? 
    End Sub 

    Private Sub _timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) 
     SyncLock Me 
      try 
       _timer.Stop() 
      catch ex as Exception    
      finally 
       _timer.Start() 
      end try 
     End SyncLock 
    End Sub 
End Class 

回答

1

只取鎖,以便調用OnStop()不能在同一時間經過的事件處理程序運行:

Protected Overrides Sub OnStop() 
     SyncLock Me 
      _timer.Stop() 
     End SyncLock 
    End Sub 

這可以比賽,經過的事件處理程序可能已經被調度運行,但沒還沒有進入鎖定。因此請驗證該計時器仍處於啓用狀態:

Private Sub _timer_Elapsed(ByVal sender As Object, ByVal e As EventArgs) 
     SyncLock Me 
      If Not _timer.Enabled Return 
      '' etc.. 

贊成專用鎖對象而不是我。並且要注意服務控制器在放棄之前願意等待的30秒時間,您正在接近。

+0

漢斯,非常感謝您的回覆。由於我不是那種用於競爭條件的:不應該在_timer_Elapsed方法中的「如果不_timer.Enabled返回」檢查在「SyncLock Me」之前?我在想(如你所說),如果Elapsed事件處理程序可能已經計劃好運行但尚未進入鎖定,那麼它應該在嘗試獲取定時器仍然啓用的鎖定之前進行檢查,即停止hasn'被叫。難道它不會導致死鎖嗎?再次感謝。 – ManOnAMission

+0

不,它必須在之後,如片段所示。你不能從Return語句中得到死鎖。 –

+0

感謝漢斯,現在明白了! – ManOnAMission