Here's a code I use for stopping threads in a Windows service (mind you I use Threads directly and not using thread pools):
// signal all threads to stop
this.AllThreadsStopSignal.Set();
if (logThreads.IsDebugEnabled)
logThreads.Debug ("Stop workers");
// remember the time of the signal
DateTime signalTime = DateTime.Now;
// create an array of workers to be stopped
List<IServiceWorker> workersToBeStopped = new List<IServiceWorker> (workers);
while (true)
{
// wait for some time
Thread.Sleep (1000);
// go through the list and see if any workers have stopped
int i = 0;
while (i < workersToBeStopped.Count)
{
IServiceWorker workerToBeStopped = workersToBeStopped [i];
if (log.IsDebugEnabled)
log.Debug (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Stopping worker '{0}'. Worker state={1}",
workerToBeStopped.WorkerDescription,
workerToBeStopped.WorkerState));
bool stopped = workerToBeStopped.JoinThread (TimeSpan.Zero);
// if stopped, remove it from the list
if (stopped)
{
workersToBeStopped.RemoveAt (i);
if (log.IsDebugEnabled)
log.Debug (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Worker '{0}' was stopped.", workerToBeStopped.WorkerDescription));
}
else
{
i++;
if (log.IsDebugEnabled)
log.Debug (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Worker '{0}' could not be stopped, will try again later. Worker state={1}",
workerToBeStopped.WorkerDescription,
workerToBeStopped.WorkerState));
}
}
// if all workers were stopped, exit from the loop
if (workersToBeStopped.Count == 0)
break;
// check if the duration of stopping has exceeded maximum time
DateTime nowTime = DateTime.Now;
TimeSpan duration = nowTime - signalTime;
if (duration > serviceCustomization.ThreadTerminationMaxDuration)
{
// execute forced abortion of all workers which have not stopped
foreach (IServiceWorker worker in workersToBeStopped)
{
try
{
log.Warn (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Aborting worker '{0}.", worker.WorkerDescription));
worker.Abort ();
log.Warn (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Worker '{0}' aborted.", worker.WorkerDescription));
}
catch (ThreadStateException ex)
{
log.Warn (String.Format (System.Globalization.CultureInfo.InvariantCulture,
"Worker '{0}' could not be aborted.", worker.WorkerDescription), ex);
}
}
break;
}
}