Ты понимаешь этот тупик?
Я использую 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!