Ты понимаешь этот тупик?

Я использую 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

Почему-то тупик с join а также GetLabel (и поэтому MainLoop?) участвует, но я не очень понимаю, что происходит. У кого-то есть больше понимания этого? Это было бы прекрасно!

2 ответа

Решение

Все инструменты GUI имеют основной поток GUI. Все они имеют специальные методы, которые позволяют вам управлять GUI-виджетами потокобезопасным способом. В мире wxPython это методы wx.CallAfter, wx.CallLater и wx.PostEvent. Я не вижу их нигде в вашем примере, поэтому вы в основном приостанавливаете поток графического интерфейса или вызываете что-то "неопределенное".

Вот пара статей о потоках и wxPython:

Я здесь вне своей области, но я подозреваю, что wxPython работает как другие наборы инструментов, отправляя сообщения в дочерние окна через поток GUI, затем ожидая ответа. В этом случае методы GetLabel() или SetLabel() должны пройти через основной цикл сообщений (== поток GUI) и остановить вызывающий поток, пока не придет ответ.

Когда вы вызываете метод cancel() из потока GUI, он устанавливает переменную abort, а затем ожидает завершения другого потока с помощью self._thread.join()поэтому никакие дальнейшие сообщения не обрабатываются, пока другой поток не остановится. Но другой поток продолжает ждать ответа на свое сообщение GetLabel() -> bingo!

Другие вопросы по тегам