我正在使用wxPython作为我的GUI。在AppLogic
类中,我有一个工作线程,它在这个类的方法中运行。
这是GUI
类:
class GUI:
_wx_app = None
_main_window = None
_app_logic = None
def start(self):
# bla bla bla
self._main_window.Show()
self._app_logic.begin()
self._wx_app.MainLoop()
def _cancel_listener(self):
"""Called from MainWindow, if the user has clicked the cancel
button."""
print("I'm leaving this scope.")
self._app_logic.cancel() # Should cancel the task done in
# a second thread.
def _status_listener(self, status_text):
"""Called often by the worker thread."""
print("Here I am again.")
if self._main_window.status.GetLabel() != status_text:
self._main_window.status.SetLabel(status_text)
以下是AppLogic
类的取消方法,该方法由_cancel_listener
从上方调用:
def cancel(self):
self._shall_abort = True
self._thread.join(self._some_time_out)
assert self._thread.isAlive() == False
不知何故,join
和GetLabel
(以及MainLoop
?)涉及到了一个僵局,但我真的不明白发生了什么。有人对此更深入了解吗?那太好了!
答案 0 :(得分:2)
我离开了我的领域,但我怀疑wxPython的工作原理与其他工具包一样,它通过GUI线程向子窗口发送消息,然后等待答案。如果是这种情况,GetLabel()或SetLabel()方法必须通过主消息循环(== GUI线程),并停止调用线程,直到答案进入。
当您从GUI线程调用cancel()时,它会设置中止变量,然后等待另一个线程以self._thread.join()
结束,因此在另一个线程停止之前不会再处理其他消息。但另一个线程一直在等待其GetLabel()消息的答案 - >宾果!
答案 1 :(得分:2)
所有GUI工具包都有一个主GUI线程。它们都有特殊的方法,允许您以线程安全的方式操作GUI小部件。在wxPython世界中,这些方法是wx.CallAfter,wx.CallLater和wx.PostEvent。我在你的例子中没有看到那些,所以你所做的基本上是暂停GUI线程或导致“未定义”发生。
以下是一些关于线程和wxPython的文章: