2012-11-19 57 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