【发布时间】:2011-07-07 03:35:30
【问题描述】:
我有一个线程化的 python 应用程序,在后台线程中有一个长时间运行的主循环。这个后台主循环实际上是对pyglet.app.run() 的调用,它驱动一个GUI 窗口,也可以配置为定期调用其他代码。我需要从主线程随意调用一个do_stuff(duration)函数来触发GUI中的动画,等待动画停止,然后返回。实际动画必须在后台线程中完成,因为 GUI 库无法处理由单独线程驱动的情况。
我认为我需要这样做:
import threading
class StuffDoer(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.max_n_times = 0
self.total_n_times = 0
self.paused_ev = threading.Event()
def run(self):
# this part is outside of my control
while True:
self._do_stuff()
# do other stuff
def _do_stuff(self):
# this part is under my control
if self.paused_ev.is_set():
if self.max_n_times > self.total_n_times:
self.paused_ev.clear()
else:
if self.total_n_times >= self.max_n_times:
self.paused_ev.set()
if not self.paused_ev.is_set():
# do stuff that must execute in the background thread
self.total_n_times += 1
sd = StuffDoer()
sd.start()
def do_stuff(n_times):
sd.max_n_times += n_times
sd.paused_ev.wait_for_clear() # wait_for_clear() does not exist
sd.paused_ev.wait()
assert (sd.total_n_times == sd.max_n_times)
编辑:使用max_n_times 而不是stop_time 来说明为什么Thread.join(duration) 不起作用。
来自threading.Event的文档:
等待([超时])
阻塞直到内部标志为真。 如果进入时内部标志为真, 立即返回。否则,阻塞 直到另一个线程调用 set() 将标志设置为真,或者直到 发生可选超时。
我发现如果我有一对事件paused_ev 和not_paused_ev 并使用not_paused_ev.wait(),我可以获得我正在寻找的行为。我几乎可以只使用Thread.join(duration),但它只需要在后台线程实际上 注册时间已到时准确返回。我应该使用其他同步对象或其他策略吗?
我也愿意接受我以错误的方式处理整个事情的论点,只要它们是好的论点。
【问题讨论】:
-
您能说明一下您要完成的工作吗?你想在主线程终止时发生一些事情吗?或者您希望在主线程运行时在特定的时间内发生一些事情?还是主线程需要向另一个线程发出信号?你的目标是什么?
-
抱歉,是的,添加了更多说明。我不想提供太多关于 GUI 的详细信息,因为我的问题主要是关于线程和阻塞。
-
我在我的问题中发现并修复了一个非常重要的问题(非常抱歉,很难测试尚未编写的代码)。我需要等待的是
paused_ev的上升沿,而它的编写方式是等待上升沿。 -
我再次查看了
threading模块文档,我认为threading.Condition可能是我需要的。我很困惑,显然不止一个线程可以acquire()它。
标签: python multithreading synchronization