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 メソッドは次のとおりです。_cancel_listener

    def cancel(self):
        self._shall_abort = True
        self._thread.join(self._some_time_out)
        assert self._thread.isAlive() == False

joinどういうわけか、 and GetLabel(したがって?) が関係しているデッドロックがあり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 に答える