У меня есть потоковое приложение на Python с длительным циклом mainloop в фоновом потоке Этот фоновый mainloop на самом деле является вызовом pyglet.app.run () , который управляет окном GUI, а также может быть настроен на периодический вызов другого кода. Мне нужно, чтобы функция do_stuff(duration)
вызывалась по желанию из основного потока для запуска анимации в графическом интерфейсе, ожидания ее остановки и возврата. Фактическая анимация должна выполняться в фоновом потоке, поскольку библиотека 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 :
ожидание ([время])
Блокировать, пока внутренний флаг не станет истинным.
Если внутренний флаг имеет значение true при входе,
Вернись немедленно. В противном случае заблокировать
пока другой поток не вызовет set () для
установите флаг в true или пока
необязательный тайм-аут.
Я обнаружил, что могу получить искомое поведение, если у меня есть пара событий paused_ev
и not_paused_ev
и использование not_paused_ev.wait()
. Я мог бы почти просто использовать Thread.join(duration)
, за исключением того, что он должен возвращать точно только тогда, когда фоновый поток на самом деле регистрирует, что время истекло. Есть ли какой-то другой объект синхронизации или другая стратегия, которую я должен использовать вместо этого?
Я также был бы открыт для аргументов, что я все это неправильно рассматриваю, при условии, что они хорошие аргументы.