0

我正在为我的 GUI 使用 wxPython。在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

不知何故,有一个死锁joinGetLabel(因此MainLoop?)涉及,但我真的不明白发生了什么。有人对此有更深入的了解吗?那太好了!

4

2 回答 2

2

我不在我的领域,但我怀疑 wxPython 像其他工具包一样工作,通过 GUI 线程向子窗口发送消息,然后等待答案。如果是这种情况,GetLabel() 或 SetLabel() 方法必须通过主消息循环(== GUI 线程),并停止调用线程,直到得到答案。

当您从 GUI 线程调用 cancel() 时,它会设置 abort 变量,然后等待另一个线程以 结束self._thread.join(),因此在另一个线程停止之前不会处理更多消息。但是另一个线程一直在等待它的 GetLabel() 消息的答案 -> 宾果游戏!

于 2012-05-11T10:22:16.510 回答
2

所有 GUI 工具包都有一个主 GUI 线程。它们都有特殊的方法,允许您以线程安全的方式操作 GUI 小部件。在 wxPython 世界中,这些方法是 wx.CallAfter、wx.CallLater 和 wx.PostEvent。我在您的示例中的任何地方都看不到这些,所以您所做的基本上是暂停 GUI 线程或导致发生“未定义”的事情。

这里有几篇关于线程和 wxPython 的文章:

于 2012-05-11T14:37:41.253 回答