我有一个 GUI 类,它只有 tkinter 小部件的实例,而不是 tkinter 的子类。这个 GUI 类也有一个数据处理对象的实例,它调用一个需要很长时间才能执行的成员函数。为了防止 GUI 冻结并更新进度条,我使用了多处理。
outqueue = mp.Queue()
objqueue = mp.Queue()
progqueue = mp.Queue()
try:
process = mp.Process(target=self.vromad.extractPlayers_mp,args=[outqueue, objqueue, progqueue])
process2 = mp.Process(target=self.vromad.extractPlayers)
process2.daemon = True
process.daemon = True
process.start()
process2.start()
print("started process")
self.frame.after(500, self.updateBar, progqueue)
print("bar should have started")
except:
self.exceptionPopUp(traceback.format_exc())
xtractStatus = -1
print("already here")
这是行为真正变得有趣的地方。我运行与第一个进程相同的第二个进程,以检查多处理是否存在任何阻塞。不,在任一任务完成之前打印“已启动的进程”。事实上,通过添加 process2.start(),CPU 使用率正好翻倍。此外,“栏应该已经开始”和“已经在这里”在栏实际更新之前打印。事实上,回调 self.updateBar 在“已经在这里”之后打印输出。
看起来当代码继续执行时,所有的 GUI 事件都被推迟到一切都空闲为止。情况确实如此,因为不仅在进程完成之前栏不会更新,而且整个窗口都会冻结。我尝试过 self.frame.after 的延迟时间短至 10 毫秒,长至 1000 毫秒,但行为没有任何变化。这是因为该进程以某种方式获得了 tkinter 的某些属性,从而阻止了 tkinter 通过其事件循环?在这里切换到线程有帮助吗?