如何启动计时器并将其重置为python?

时间:2020-10-08 09:09:20

标签: python

我已经在类上初始化了一个计时器,在指定的秒数之后,它将调用另一个目标函数。这种情况正在加载,它将显示欢迎功能gui并打开串行端口。

关于通过串行端口接收的数据,我想查询Web api上的信息,并在显示信息之后,想要启动在__init__上声明的计时器。

但是,如果在命中计时器之前另一个数据从串行端口进入,我希望计时器随着更多数据的到来而重启/复位,那么我不必再次显示欢迎功能,直到在计时器运行之间没有任何东西进入为止。

我从这个answer中找到了一些东西,但是它没有触发回调函数

from threading import Thread, Timer

class TimerThread(threading.Thread):
    def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
        threading.Thread.__init__(self)
        print('timer:initialized')
        self.timeout = timeout
        print('timeout:' + str(timeout))
        self.sleep_chunk = sleep_chunk
        print('timeout:' + str(sleep_chunk))
        if callback == None:
            self.callback = None
            print('callback:none')
        else:
            self.callback = callback
            print('callback:' + str(callback))
        self.callback_args = args

        self.terminate_event = threading.Event()
        self.start_event = threading.Event()
        self.reset_event = threading.Event()
        self.count = self.timeout/self.sleep_chunk

    def run(self):
        print('timer:run')
        while not self.terminate_event.is_set():
            while self.count > 0 and self.start_event.is_set():
                if self.reset_event.wait(self.sleep_chunk):  # wait for a small chunk of timeout
                    self.reset_event.clear()
                    self.count = self.timeout/self.sleep_chunk  # reset
                self.count -= 1
            if self.count <= 0:
                self.start_event.clear()
                print('timeout. calling function...')
                self.callback(*self.callback_args)
                self.count = self.timeout/self.sleep_chunk  # reset

    def start_timer(self):
        print('start_timer')
        self.start_event.set()

    def stop_timer(self):
        print('stop_timer')
        self.start_event.clear()
        self.count = self.timeout / self.sleep_chunk  # reset

    def restart_timer(self):
        # reset only if timer is running. otherwise start timer afresh
        print('restart_timer')
        if self.start_event.is_set():
            self.reset_event.set()
            print('restart_timer:reset')
        else:
            self.start_event.set()
            print('restart_timer:start')

    def terminate(self):
        print('terminate')
        self.terminate_event.set()

class Application(Tk):
    def show_idle_screen(self):
        for widget in self.winfo_children():
            widget.destroy()
        # Create new widget element

    def show_product_info(self, barcodeno):
        # call web api and get response
        # create information widget element
        # -Timer(5.0, self.show_idle_screen).start()
        tmr = TimerThread(timeout, sleep_chunk, Application().show_idle_screen)
        tmr.restart_timer()


    def serial_port_data_received(self):
        if self.serial.inWaiting() > 0:
            # The rest of handling serial data
            # UPDATED CODE START
            # -if self.idle_timer.is_alive():
            #     -print('cancelling timer')
            #     -self.idle_timer.cancel()
            # UPDATED CODE END
            self.query_thread = Thread(target=lambda: self.show_product_info(barcodedata))
            self.query_thread.start()


    def __init__(self):
            # Initialization of timer
            # -self.idle_timer = Timer(5.0, self.show_idle_screen)
            self.new_thread = Thread(target=self.show_idle_screen)
            self.new_thread.start()

root = Application()
root.mainloop()

日志:

timer:initialized
timeout:6
timeout:0.25
callback:<bound method Application.show_idle_screen of <__main__.Application object .>>
start_timer

1 个答案:

答案 0 :(得分:0)

经过反复尝试,我终于可以运行所需的内容。

from threading import Thread, Timer

class TimerThread(threading.Thread):
    def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
        threading.Thread.__init__(self)
        print('timer:initialized')
        self.timeout = timeout
        print('timeout:' + str(timeout))
        self.sleep_chunk = sleep_chunk
        print('timeout:' + str(sleep_chunk))
        if callback == None:
            self.callback = None
            print('callback:none')
        else:
            self.callback = callback
            print('callback:' + str(callback))
        self.callback_args = args

        self.terminate_event = threading.Event()
        self.start_event = threading.Event()
        self.reset_event = threading.Event()
        self.count = self.timeout/self.sleep_chunk

    def run(self):
        print('timer:run')
        while not self.terminate_event.is_set():
            while self.count > 0 and self.start_event.is_set():
                if self.reset_event.wait(self.sleep_chunk):  # wait for a small chunk of timeout
                    self.reset_event.clear()
                    self.count = self.timeout/self.sleep_chunk  # reset
                self.count -= 1
            if self.count <= 0:
                self.start_event.clear()
                print('timeout. calling function...')
                self.callback(*self.callback_args)
                self.count = self.timeout/self.sleep_chunk  # reset

    def start_timer(self):
        print('start_timer')
        self.start_event.set()

    def stop_timer(self):
        print('stop_timer')
        self.start_event.clear()
        self.count = self.timeout / self.sleep_chunk  # reset

    def restart_timer(self):
        # reset only if timer is running. otherwise start timer afresh
        print('restart_timer')
        if self.start_event.is_set():
            self.reset_event.set()
            print('restart_timer:reset')
        else:
            self.start_event.set()
            print('restart_timer:start')

    def terminate(self):
        print('terminate')
        self.terminate_event.set()

class Application(Tk):
    def show_idle_screen(self):
        for widget in self.winfo_children():
            widget.destroy()
        # Create new widget element
        print('idle_screen')

    def show_product_info(self, barcodeno):
        # call web api and get response
        # create information widget element
        # -Timer(5.0, self.show_idle_screen).start()
        # -tmr = TimerThread(timeout, sleep_chunk, Application().show_idle_screen)
        # -tmr.restart_timer()
        self.tmr.restart_timer()


    def serial_port_data_received(self):
        if self.serial.inWaiting() > 0:
            # The rest of handling serial data
            # UPDATED CODE START
            # -if self.idle_timer.is_alive():
            #     -print('cancelling timer')
            #     -self.idle_timer.cancel()
            # UPDATED CODE END
            self.query_thread = Thread(target=lambda: self.show_product_info(barcodedata))
            self.query_thread.start()


    def __init__(self):
            # Initialization of timer
            # -self.idle_timer = Timer(5.0, self.show_idle_screen)
            self.tmr = TimerThread(timeout, sleep_chunk, self.show_idle_screen)
            self.tmr.start()
            self.tmr.start_timer()
            self.new_thread = Thread(target=self.show_idle_screen)
            self.new_thread.start()

root = Application()
root.mainloop()

日志:

idle_screen
timeout. calling function...
idle_screen
Going to query information for data
restart_timer
restart_timer:start
timeout. calling function...
idle_screen
Going to query information for data