我有一個線程化的Python應用程序,在後臺線程中有一個長時間運行的主循環。此背景主循環實際上是對pyglet.app.run()的調用,它驅動GUI窗口,並且可以配置爲定期調用其他代碼。我需要從主線程中隨意調用do_stuff(duration)
函數來觸發GUI中的動畫,等待動畫停止,然後返回。實際的動畫必須在後臺線程中完成,因爲GUI庫無法處理被單獨的線程驅動。阻止主線程,直到python後臺線程完成側任務
我相信我需要做這樣的事情:
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()爲 將該標誌設置爲true,或者直到發生可選超時 。
我發現我可以得到我要找的,如果我有一雙事件,paused_ev
和not_paused_ev
的行爲,並使用not_paused_ev.wait()
。我幾乎可以使用Thread.join(duration)
,除了它只需要在後臺線程實際上註冊時間結束時才精確返回。是否有其他同步對象或其他策略我應該使用?
我也願意接受這樣一個觀點,即我以錯誤的方式接近整個事情,只要他們是很好的論點。
您能否澄清一下您試圖完成的任務?當主線程終止時你想要發生什麼?或者你想要在主線程運行的時間內發生一段特定的時間?或者主線程需要發信號給另一個線程?你的目標是什麼? –
對不起,是的,增加了更多的說明。我不想給太多關於GUI的細節,因爲我的問題主要是關於線程和阻塞。 –
我發現並解決了一個非常重要的問題(非常抱歉,很難測試未寫入的代碼)。我需要等待的是'paused_ev'的一個上升沿,它寫入的方式正在等待一個_rising_邊緣。 –