2012-07-11 12 views
33

Lo que trato de hacer aquí es usar una interrupción de teclado para salir de todos los hilos en curso en el programa. Esta es una versión pelado abajo de mi código donde se crea el hilo:Cerrar todos los hilos con una interrupción de teclado

for i in taskDictionary: 
    try: 
     sleep(60) 
     thread = Thread(target = mainModule.executeThread) 
     thread.start() 
    except KeyboardInterrupt: 
     thread.__stop() 

El programa en sí es mucho más complicado, lo que representa toneladas de diferentes variables que afectan los hilos e incluso tienen la opción de poner en marcha de manera secuencial modo, donde las tareas no están enhebradas, sino que se lanzan una por una, por lo que podría haber algunos problemas con esta pequeña variación que acabo de conjurar. He hecho esto de forma que produjo 50/50 resultados. Las interrupciones funcionarían pero los hilos nunca saldrían limpiamente. Algunas veces continuarían pero detendrían la ejecución de hilos futuros, algunas veces saldrían con un error masivo con respecto a la interrupción, otras veces las interrupciones no harían nada. La última vez que ejecuté esto, el programa detuvo la ejecución de los hilos futuros, pero no detuvo el hilo actual. ¿Hay alguna manera de salir de los hilos sin entrar en el módulo en el que se está ejecutando el hilo?

Respuesta

52

Una pregunta similar es "¿Cómo se mata un hilo?"

Crea un controlador de salida en el hilo controlado por un objeto de bloqueo o evento del módulo de subprocesamiento. A continuación, simplemente quite el bloqueo o señalice el objeto del evento. Esto informa al hilo que debe detener el procesamiento y salir con gracia. Después de señalar el hilo en su programa principal, lo único que queda por hacer es usar el método thread.join() en main que esperará a que el hilo se cierre.

Un breve ejemplo:

import threading 
import time 

def timed_output(name, delay, run_event): 
    while run_event.is_set(): 
     time.sleep(delay) 
     print name,": New Message!" 


def main(): 
    run_event = threading.Event() 
    run_event.set() 
    d1 = 1 
    t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event)) 

    d2 = 2 
    t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event)) 

    t1.start() 
    time.sleep(.5) 
    t2.start() 

    try: 
     while 1: 
      time.sleep(.1) 
    except KeyboardInterrupt: 
     print "attempting to close threads. Max wait =",max(d1,d2) 
     run_event.clear() 
     t1.join() 
     t2.join() 
     print "threads successfully closed" 

if __name__ == '__main__': 
    main() 

Si realmente necesita la funcionalidad de matar un hilo, utilice el multiprocesamiento. Le permite enviar SIGTERMs a "procesos" individuales (también es muy similar al módulo de subprocesamiento). En términos generales, el enhebrado es para cuando está vinculado a IO, y el multiprocesamiento es para cuando está verdaderamente vinculado al procesador.

+7

Con la cooperación de un hilo, puede matarlo como quiera. Sin la cooperación de un hilo, no hay una forma segura de hacerlo y todos los caminos provocan dolor. –

+1

Brillante respuesta! ¡No es exactamente lo que estaba buscando pero lo suficientemente extenso como para adaptar la lógica a lo que necesitaba! ¡Gracias por eso! – Joe

+1

Estoy usando un hilo porque no quiero un ciclo infinito mientras sea True. Esto desperdicia todo el tiempo de tu CPU ... más o menos literalmente. He hecho algo como esto y sin dormir genera CPU% hasta 100% por ** segundos ** a la vez y con un pequeño descanso, esto solo ayuda un poco. ¿Hay alguna manera de hacer esto ** sin ** un tiempo cierto? – dylnmc

Cuestiones relacionadas