Как правильно остановить однопоточную службу Windows (onStop)?

У меня есть служба Windows, написанная на VS 2010 / .NET 4.0.

Служба работает по схеме приведенного ниже фрагмента кода: используя таймер, она выполняет желаемое поведение каждые пару минут. Требование "желаемого поведения", которое выполняется каждые пару минут, теперь переросло в работу, которая занимает примерно 10 секунд.

Мне нужен только один поток в этом сервисе, нет причин создавать несколько потоков, поэтому я назвал службу Windows однопоточным.

Меня беспокоит то, что если кто-то останавливает службу через консоль управления, это может быть как раз в течение тех 10 секунд работы, которые иногда выполняет служба.

Я немного читал о SO и о том, как остановить службу, но немного растерялся. Иногда создаются 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() не мог работать одновременно с обработчиком событий Elapsed:

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

Который может участвовать в гонке, обработчик событий Elapsed, возможно, уже запланирован для запуска, но еще не вошел в блокировку. Поэтому убедитесь, что таймер все еще включен:

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

Пользуйся выделенным объектом блокировки вместо Меня. И следите за 30 секундами, которые сервисный контроллер готов подождать, прежде чем сдаться, вы приближаетесь.

Другие вопросы по тегам