2012-06-18 15 views
12

me di cuenta el siguiente comportamiento en el siguiente código (usando la clase threading.Timer):Python - threading.Timer permanece vivo después de llamar a cancelar() método

import threading 

def ontimer(): 
    print threading.current_thread() 

def main(): 
    timer = threading.Timer(2, ontimer) 
    timer.start() 
    print threading.current_thread() 
    timer.cancel() 
    if timer.isAlive(): 
     print "Timer is still alive" 
    if timer.finished: 
     print "Timer is finished" 


if __name__ == "__main__": 
main() 

La salida del código es:

<_MainThread(MainThread, started 5836)> 
Timer is still alive 
Timer is finished 

Como notamos en la salida, que el objeto del temporizador sigue vivo y terminado al mismo tiempo.

De hecho, me gustaría llamar a una función similar cientos de veces, y me pregunto si los temporizadores "vivos" pueden afectar el rendimiento.

Me gustaría detener o cancelar el objeto del temporizador de forma adecuada. ¿Lo estoy haciendo bien?

Gracias

Respuesta

11

Un Timer es una subclase de una Thread y su implementation es muy simple. Espera el tiempo proporcionado al suscribirse al evento finished.

Por lo tanto, cuando configura el evento por Timer.cancel, se garantiza que no se llamará a la función. Pero no está garantizado que el hilo del temporizador continúe directamente (y salga).

Entonces, el punto es que el hilo del temporizador aún puede estar vivo después de la ejecución de cancel, pero la función no se ejecutará. Por lo tanto, comprobar finished es seguro, mientras que las pruebas de Thread.is_alive (API más reciente, ¡utilice esto!) Es una condición de carrera en este caso.

Sugerencia: Puede verificar esto colocando un time.sleep después de llamar al cancel. A continuación, se acaba de imprimir:

<_MainThread(MainThread, started 10872)> 
Timer is finished 
10

Se debe utilizar la thread.join() que esperar hasta que el hilo de su contador de tiempo es realmente terminado y limpiado.

import threading 

def ontimer(): 
    print threading.current_thread() 

def main(): 
    timer = threading.Timer(2, ontimer) 
    timer.start() 
    print threading.current_thread() 
    timer.cancel() 
    timer.join()   # here you block the main thread until the timer is completely stopped 
    if timer.isAlive(): 
     print "Timer is still alive" 
    else: 
     print "Timer is no more alive" 
    if timer.finished: 
     print "Timer is finished" 


if __name__ == "__main__": 
main() 

esta pantalla:

<_MainThread(MainThread, started 5836)> 
Timer is no more alive 
Timer is finished 
+0

Gracias por elaboración. –

Cuestiones relacionadas