我已经在类上初始化了一个计时器,在指定的秒数之后,它将调用另一个目标函数。这种情况正在加载,它将显示欢迎功能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
答案 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