Search code examples
windowsvb.netservice

How do I wait for a worker process to finish but also limit it's time to do so?


I am writing a Windows service in VB.Net that will go out to some devices and data log points of information. I am using a Background Worker to do that so the service itself is still responsive. I have a timer that runs every second and checks the minute component of the current time. Each time the minute component changes I check which devices need to be checked, some are every minute, some every 5, some every 10, etc. These processes can take a few seconds or over a minute (I only rerun the worker if it's not already running and log a error if the last process took longer then the data retrieval interval).

In my OnStop event for the service I want to make sure the workers all close down. I call CancelAsync on the worker and the worker checks for cancellation to hopefully exit cleanly (i.e., check cancelation, if false retrieve data, save data into database, loop).

My problem is I don't want to use a sleep statement as it will lock everything but I also don't want the service to never shut down. So for example I have this currently:

Protected Overrides Sub OnStop()
    ' Add code here to perform any tear-down necessary to stop your service.
    My.Application.Log.WriteEntry("ServiceABC shutting down for device " & DeviceID)
    ServiceTimer.enable = false
    If DataRetrievalBackgroundWorker.IsBusy Then
        DataRetrievalBackgroundWorker.CancelAsync()
        Dim x As Integer = 0
        While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
            Threading.Thread.Sleep(1000)
            x += 1
        End While
    End If
End Sub

This should work since the background worker is on another thread correct? Is there a better way to handle this?


Solution

  • You're close, if you don't want to Sleep(1000) and lock things up, do a Sleep(1).

        'Dim x As Integer = 0
        'While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
        '    Threading.Thread.Sleep(1000)
        '    x += 1
        'End While
    
        Dim T As Date = Now.AddSeconds(15)
        While DataRetrievalBackgroundWorker.IsBusy Or Now() < T
            Threading.Thread.Sleep(1)
            Application.DoEvents()
        End While