1

I have a short and probably simple question refering to Timers: Is it normal for the thread ID to increment every time I start a timer?

from threading import Timer

class Watchdog():
    def __init__(self, timeout, user_Handler):  # timeout in seconds
        self.timeout = timeout
        self.handler = user_Handler
        self.timer = Timer(self.timeout, self.handler)

    def reset(self):
        self.timer.cancel() # stop the timer's action if it's still running
        print("A", self.timer)
        self.timer = Timer(self.timeout, self.handler) # Timer: Calls a function=handler after a specified number of seconds
        print("B", self.timer)
        self.timer.start()
        print("C", self.timer) 

    def stop(self):
        """Stop the timer if it hasn't finished yet."""
        self.timer.cancel()
        print("D", self.timer)

When I use my class, the print statements return sth similar like this:

print(self.timer) 
>>> <Timer(Thread-1, started daemon 19447202672)>
>>> <Timer(Thread-2, stopped daemon 19447202672)>
...
>>> <Timer(Thread-n, started daemon 19447202672)>

--> n (=ID) rises

Reference: How to implement a watchdog timer in Python?

UPDATE - Use of the class: As I use this class with a button which triggers an interrupt, I'll try a textual description. I'm pretty sure, this might be enough for a python/programming expert (If not, please tell me).

A push of the button changes the view of a LC-Display from a default view to one of three special views. After the last special view it starts again with the default view (kind of round robin). After 5s without pushing the button, screen is resetted to default view.

Pushing the button calls the watchdog interrupt handler where my_watchdog.reset() is called to start the watchdog timer. By changing the view (button push) within the 5s , this happens again and so the timer is resetted by being canceled and started. If you switch from the last special view to the default view by hand, my_watchdog.stop() is called. This is to avoid the call of the watchdog_expired_handler. This handler resets the view to the default view.

In summary you could say that my_watchdog is instantiated and my_watchdog.reset() and my_watchdog.stop() are called at random times.

UPDATE_2 - Simplified use of the class in python:

import time

def watchdog_handler():
    print("watchdog timer expired")

my_watchdog = Watchdog(timeout=5, user_Handler=watchdog_handler)

my_watchdog.reset() # starts a watchdog timer (no running timer has to be stopped)
time.sleep(6) # is equivalent to no action of the user
my_watchdog.reset() # user presses button again
time.sleep(2) # user presses button while timer is still running --> watchdog.reset() is called
my_watchdog.reset()
time.sleep(2) # user presses button while timer is still running
my_watchdog.reset()
time.sleep(2) # user presses button while timer is still running and reaches default view again
my_watchdog.stop()

Output of the simplified use (on Raspian OS):

A <Timer(Thread-106, initial)>
B <Timer(Thread-107, initial)>
C <Timer(Thread-107, started 14176)>
watchdog timer expired
A <Timer(Thread-107, stopped 14176)>
B <Timer(Thread-108, initial)>
C <Timer(Thread-108, started 1256)>
A <Timer(Thread-108, stopped 1256)>
B <Timer(Thread-109, initial)>
C <Timer(Thread-109, started 6796)>
A <Timer(Thread-109, stopped 6796)>
B <Timer(Thread-110, initial)>

I've written a lot and learned also sth by breaking it down here. I think the key questions are very simple:

Is there anything critical about re/starting the timer on a new thread (I assume that this is what I do). What happens to the old one (is there some kind of garbage collector)? When is the ID reset, on restart?

  • Can you include how you use the class? Always include enough that anyone can run the code exactly as you posted it and see what you're seeing. – Dennis Dec 24 '21 at 07:05

0 Answers0