Pregunta

Tengo un servicio de Windows que tiene una serie de hilos que deben detener todos antes de que el servicio se detenga. Estoy usando este modelo para detener mis hilos y señalar que se han detenido:

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

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

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

Cuando llega el momento de cerrar mi servicio para que se detenga, solo configuré la ejecución en falso y llame al set () en todos los autoresetos que existen. Esto indica instantáneamente los hilos para que dejen de dormir o para que se detengan una vez que hayan terminado de procesar en lo que están trabajando. Esto funciona muy bien. Pero, la parte por la que más estoy nervioso es verificar que todo se haya detenido. Esto es lo que estoy haciendo ahora:

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

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

La razón principal por la que no me gusta esto es que se basa en el tiempo, y si uno de mis hilos está en medio de una operación larga (lo que es muy probable), el apagado puede no terminar en esos 25 segundos (y es Muy importante que todos estos hilos se cierren para el momento en que se ejecuta este código, termina). No puedo eliminar los intentos porque si uno de esos hilos cuelga (no lo hacen, pero nunca se sabe), entonces estoy realmente atrapado y el servicio nunca se detendrá.

¿Existe una mejor manera de hacer la verificación de que todos los hilos se han detenido, preferiblemente uno que no esté basado en el tiempo? ¿O estoy condenado a tener algún tipo de tiempo de espera que podría necesitar ser mucho más largo (10 intentos con un sueño de 30 segundos, tal vez)?

¿Fue útil?

Solución

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top