I noticed the following behavior in the following code (using 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()
The output of the code is:
<_MainThread(MainThread, started 5836)>
Timer is still alive
Timer is finished
As We notice from the output, that the timer object is still alive and finished in the same time.
In fact, I would like to call a similar function hundreds of times, and I wonder whether those "living" timers may affect the performance.
I would like to stop or cancel the timer object in a proper way. Am I doing it right?
Thank you
You should use the thread.join() to wait until your timer's thread is really finished and cleaned.
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()
This will display :
<_MainThread(MainThread, started 5836)>
Timer is no more alive
Timer is finished
A Timer
is a subclass of a Thread
and its implementation is really simple. It waits the provided time by subscribing to the event finished
.
So when you set the event by Timer.cancel
it is guaranteed that the function does not get called. But it is not guaranteed that the Timer thread will directly continue (and exit).
So the point is that the thread of the timer can still be alive after the execution of cancel
, but the function will not get executed. So checking for finished
is safe, while testing for Thread.is_alive
(newer API, use this!) is a race condition in this case.
Hint: You can verify this by placing a time.sleep
after calling cancel
. Then it will just print:
<_MainThread(MainThread, started 10872)>
Timer is finished
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With