Подтвердить что ты не робот

Python - threading.Timer остается в живых после вызова метода cancel()

Я заметил следующее поведение в следующем коде (используя threading.Timer class):

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()

Вывод кода:

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

Как мы видим из вывода, объект таймера все еще жив и завершен в одно и то же время.

На самом деле, я хотел бы вызвать аналогичную функцию сотни раз, и мне интересно, могут ли эти "живые" таймеры влиять на производительность.

Я хотел бы остановить или отменить объект таймера соответствующим образом. Правильно ли я делаю это?

Спасибо

4b9b3361

Ответ 1

A Timer является подклассом a Thread и его реализация действительно проста. Он ожидает установленное время, подписавшись на событие finished.

Поэтому, когда вы устанавливаете событие на Timer.cancel, гарантируется, что функция не будет вызвана. Но не гарантируется, что поток таймера будет напрямую продолжать (и выйти).

Итак, дело в том, что поток таймера может оставаться в живых после выполнения cancel, но функция не будет выполнена. Таким образом, проверка на finished безопасна, а тестирование для Thread.is_alive (новый API, используйте это!) - это условие гонки в этом случае.

Подсказка: вы можете проверить это, поместив time.sleep после вызова cancel. Затем он просто напечатает:

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

Ответ 2

Вы должны использовать thread.join(), чтобы дождаться завершения и очистки потока таймера.

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()

Это отобразит:

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