按需触发的周期性Python线程
我有一个简单的PyGTK应用程序。因为我需要定期执行多个任务来获取一些数据并刷新界面,所以我像这样扩展了线程:
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()
我在应用程序启动时启动这些线程,把它们保存在一个列表里,并在退出前取消它们。这样做效果很好。
但现在我想添加一个刷新按钮,这样可以强制其中一个线程立即运行,而不是等到设定的时间再运行(如果它当前没有在运行的话)。
我尝试通过在MyThread中添加一个布尔变量来表示线程是否正在运行(在_run之前设置为真,完成时重置为假),然后如果没有在运行就直接调用MyThread._run(),但这样导致我的应用程序变得无响应,_run任务也永远无法完成。
我不太明白为什么会这样。解决这个问题的最佳方法是什么?如果我能让刷新在后台运行,这样就不会阻塞界面,那也很好。
也许可以调用run,并把秒数设置为1,这样计时器就能更快触发它?
1 个回答
4
与其使用一个 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秒打印一次,依此类推。