문제

I have a Windows service that has a number of threads that all need to be stopped before the service stops. I'm using this model for stopping my threads and signalling that they have been stopped:

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
    Thread1Running = true;

    try
    {
        while (running)
        {
            AutoReset1.WaitOne(TimeSpan.FromSeconds(30.0));

            if (running)
            {
                // do stuff
            }
        }
    }
    finally
    {
        Thread1Running = false;
    }
}));

When it comes time to shut my service to stop, I just set running to false and call Set() on all the AutoResets out there. This instantly signals the threads to stop sleeping or to stop once they've finished processing what they're working on. This works really well. But, the part that I'm most nervous about, is verifying that everything has stopped. This is what I'm doing now:

Int32 tries = 0;
while (tries < 5 && (Thread1Running || Thread2Running || Thread3Running))
{
    tries++;

    Thread.Sleep(TimeSpan.FromSeconds(5.0));
}

The main reason that I don't like this is that it's time based, and if one of my threads is in the middle of a lengthy operation (which is quite likely), the shut down may not finish in that 25 seconds (and it's very important that all of these threads be shut down by the time OnStop, where this code gets run, finishes). I can't remove the tries because if one of those threads hangs (they don't, but you never know), then I'm really stuck and the service will never stop.

Is there a better way to do the verification that the threads have all stopped, preferably one that isn't time based? Or am I doomed to having some sort of timeout that might just need to be much longer (10 tries with a 30 second sleep, maybe)?

도움이 되었습니까?

해결책

I believe the general method for doing this is to join on the threads. The specifics of the call will depend on the threading library you're using, but in general the join method will block until the thread has exited (and should return immediately if the thread is already dead). So you could just join on all your threads in sequence, then exit. If all your joins have returned then all the threads have exited.

Many threading libraries allow you to add a timeout to join, which you would probably want to do. This way even if one of your threads hangs your exit code doesn't block.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top