我有简单的PyGTK应用程序。因为我必须运行多个周期性任务来获取一些数据并刷新GUI,所以我像这样扩展了Thread:
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.setDaemon(True)
self.event = threading.Event()
self.event.set()
def run(self):
while self.event.is_set():
timer = threading.Timer(60, self._run)
timer.start()
timer.join()
def cancel(self):
self.event.clear()
def _run(self):
gtk.threads_enter()
# do what need to be done, fetch data, update GUI
gtk.threads_leave()
我在app bootstrap上启动线程,将它们保存在某个列表中并在退出之前取消它们。这非常完美。
但是现在我想添加刷新按钮,它会强制其中一个线程立即运行而不是等待一段时间才能运行,如果当前没有运行的话。
我尝试通过向MyThread添加bool var来指示线程是否正在运行(在_run之前设置,在完成时重置),然后如果没有运行则调用MyThread._run(),但这会导致我应用程序无法响应和_run任务永远不会完成执行。
我不确定为什么会这样。解决这个问题的最佳方法是什么?如果我可以在后台运行刷新以便它不会阻止GUI,那也没关系。
也许要调用run并将秒数传递给1,这样定时器可以更快触发它?
答案 0 :(得分:2)
不使用Timer
,而是使用另一个Event
对象和超时。然后,您可以在按钮回调中设置该事件。下面的代码说明了这一点(我已经删除了你的取消代码以保持简短):
import threading
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.sleep_event = threading.Event()
self.damon = True
def run(self):
while True:
self.sleep_event.clear()
self.sleep_event.wait(60)
threading.Thread(target=self._run).start()
def _run(self):
print "run"
my_thread = MyThread()
my_thread.start()
while True:
raw_input("Hit ENTER to force execution\n")
my_thread.sleep_event.set()
默认情况下,“run”将每60秒打印一次。如果你点击ENTER,它将立即打印,然后在60秒后再打印等