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
Как мы видим из вывода, объект таймера все еще жив и завершен в одно и то же время.
На самом деле, я хотел бы вызвать аналогичную функцию сотни раз, и мне интересно, могут ли эти "живые" таймеры влиять на производительность.
Я хотел бы остановить или отменить объект таймера соответствующим образом. Правильно ли я делаю это?
Спасибо
Ответы
Ответ 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