你明白这个僵局了吗?

时间:2012-05-11 10:16:13

标签: python multithreading join wxpython deadlock

我正在使用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

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

2 个答案:

答案 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的文章: