多处理在Python中冻结/挂起tkinter GUI

时间:2013-09-18 09:47:05

标签: python user-interface tkinter multiprocessing freeze

我有一个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使用率正好翻了一番。此外,在条形图实际更新之前,“bar应该已经开始”并且“已经在这里”被打印。事实上,回调self.updateBar打印输出AFTER“已经在这里。”

在代码继续优异的情况下,所有GUI事件都会延迟,直到所有内容都处于空闲状态。这看起来确实如此,因为在进程完成之前,条形图不仅不会更新,而且整个窗口都会冻结。我已经尝试过self.frame.after的延迟时间,短至10毫秒,长达1000毫秒,行为没有变化。这是因为进程以某种方式得到tkinter的某些属性阻止tkinter通过其事件循环?切换到线程会有帮助吗?

1 个答案:

答案 0 :(得分:0)

我发现了什么问题。虽然处理按钮按下的命令产生了一个新的进程来完成工作,但它正在阻塞somequeue.get()并等待工作完成。由于命令处理在与tkinter的mainloop()相同的线程中运行,因此mainloop()事件被阻塞,导致此处出现问题。这可以通过将somequeue.get()代码移动到另一个不会阻塞的函数来解决,直到所有工作都完成。此函数还会更新进度条,同时检查队列中的某些标记值,表明所有工作都已完成。

这是重点。完成所有工作后,该功能会阻止 ONLY