2

I created a Windows service in VB.NET. The OnStart creates a worker thread and returns. The worker thread starts up ok and attempts to connect to a db. If the connection is made, the thread goes into an infinite loop, which is the expected behavior.

Dim _shutdown As Boolean = False 
Private _oPollingThread As Thread

Protected Overrides Sub OnStart(ByVal args() As String)
    _oPollingThread = New Thread(New System.Threading.ThreadStart(AddressOf PollProcess))
    _oPollingThread.Start()
End Sub

If the service is shut down manually (by a Windows user going into Services and clicking Stop), the OnStop sets a boolean; the worker thread sees this and shuts itself down successfully, the OnStop joins, and the service stops. All good.

Protected Overrides Sub OnStop()
    _shutdown = True

    ' Allow poll process to shut down gracefully (give it up to ten seconds...)
    Dim shutdownCount As Integer = 0

    Do While _oPollingThread.Join(1000) = False And shutdownCount < 10
        shutdownCount = shutdownCount + 1
    Loop

    If _oPollingThread.IsAlive = True Then
        _oPollingThread.Abort()
    End If

End Sub

The problem is, how do I get the service to stop if the worker thread does not connect to the db? Once the worker thread terminates (instead of going into its infinite loop), the Windows service stays active and OnStop does not run.

  • 1
    Can you use a backgroundworker? It raises a RunWorkerCompleted event when it's done, so you just have to have a sub that handles that event. http://stackoverflow.com/questions/5551258/c-net-how-to-alert-program-that-the-thread-is-finished-event-driven – Tony Hinkle May 21 '15 at 18:31

1 Answers1

0

Hmm, I think Tony Hinkle may be on the right track with the events, though I'm not sure you'd need the BackgroundWorker. Could you declare a WorkerStopped event that gets raised by the worker thread? Then the service could have a Sub that handles it and stops the service.

It'd look something like this:

Public Class WinService
    '...OnStart(), OnStop()...

    Dim _shutdown As Boolean = False
    Private _oPollingThread As Thread
    Private Event WorkerStopped(sender As Object, e As EventArgs)

    Private Sub PollProcess()
        '...Attempt to connect to db...

        'See if attempt was successful, raise event if not.
        If databaseConnectionFailed Then
            RaiseEvent WorkerStopped(Me, Nothing) 'Could pass back data (error msg?) in EventArgs if desired
        Else
            'Connected to db successfully; proceed
            '...
        End If
    End Sub

    Private Sub StopWork(sender As Object, e As EventArgs) Handles Me.WorkerStopped
        Me.Stop()
    End Sub
End Class

If you want to get fancy you could declare your own custom WorkerStoppedEventArgs type and pass that instead of the vanilla EventArgs. Or where it's custom, you could have it take no arguments at all, but I like to follow convention there.

I wish I could guarantee this'd work, but it's been ~6 years since I wrote a Windows Service and as I recall they're not real easy to just fire up and try!

Arin
  • 1,373
  • 2
  • 10
  • 23
  • I implemented the BackgroundWorker solution suggested by Tony Hinkle; however, the RaiseEvent + event handler solution looks good. Thank you for the elegant suggestion. – user3076228 May 21 '15 at 23:19