具有按需触发器的定期Python线程

时间:2011-12-16 09:13:33

标签: python multithreading pygtk task python-multithreading

我有简单的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,这样定时器可以更快触发它?

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秒后再打印等