views:

129

answers:

4

I've got a Windows Service that runs BackgroundWorker's, and I'm wondering if I'm doing the right thing when I stop my Windows Service.

Is it enough to:

  1. Let the BackgroundWorker1_DoWork method complete (I have a while loop in it now, doing some tasks)
  2. Set the variable that holds the reference to the BackgroundWorker, to null

Is there some kind of Dispose() method I need to call (In the same way the Timer class has Timer.Dispose();)?

A: 

The correct method is to let the worker thread cleanly finish what it is doing.

This can often be done by having a shared flag\waithandle\whatever that can be used to communicate to the worker thread (from the main thread) that it should exit what it is doing, which will naturally lead to the worker thread shuffling off its stack and evaporating. The worker thread should regularly check the "flag" to see if it it needs to exit (e.g. in your loop), and the main service thread can signal the flag when it needs to shut down. The main thread then waits for the worker thread to exit e.g. by calling join on the worker thread.

chibacity
A: 

BackgroundWorker is IDisposable, so you should dispose of it when you no longer need to.

BackgroundWorkers also have a CancelAsync method that changes the CancellationPending property to true. You can check for that in your DoWork function so you can stop it from running.

rossisdead
+1  A: 

Frankly, when you stop your windows service - it really doesn't matter. Your win32 process is terminated, so its not strictly necessary to clean up your IDisposables. Any unmanaged resources will have a finalizer that will still run.

That said, it's normal to have a class level background worker that gets disposed when e service class does. Not necessary, but it's always good to be clean.

Mark Brackett
When you stop a windows service, the SCM (Service Control Manager) will call into your Stop interface and wait a default period of time before it kills you - I think it is 15 seconds by default. In this time you can cleanly shut down your service.
chibacity
+1  A: 

Since BackgroundWorker implements IDisposable, you should be disposing it when you are finished with it.

You mention that this is in a Windows service so there are a few things that come into play here. When you stop a Windows service, you get around 30 seconds to return from the OnStop method in your ServiceBase implementation. If you do not return within this time, Windows reports to the user that it could not stop the service. What you should do is signal to the BackgroundWorker that you need it to stop (using the CancelAsync mechanism), dispose of the worker, and then exit. However, since you are stopping the service, it doesn't really matter as the whole process will be terminated anyway, including any threads that are running within it.

If you were to do as you say and wait for the worker to complete (in the OnStop method), your service may appear to the user as if it has hung as Windows will say that it cannot stop it, and the process will still be running.

adrianbanks