#python #multithreading #qt #qthread #pyside2
#python #многопоточность #qt #qthread #pyside2
Вопрос:
Используя PySide2
, у меня есть вспомогательный поток, выполняющий цикл фоновых событий. После закрытия моего приложения я хотел бы, чтобы quit()
вспомогательный поток и wait()
для него завершили свои события.
Однако в моем приложении возникает тупик (или что-то в этом роде), как только я вызываю wait()
. Чтобы продемонстрировать эту проблему, я создал небольшой образец приложения с подклассом, QThread
который запускает цикл событий путем вызова exec_()
, а затем имитирует длительное время выхода с некоторыми макетами очистки. отпечатки.
import sys
import time
from PySide2.QtCore import QThread
from PySide2.QtWidgets import QApplication, QMainWindow
class AuxThread(QThread):
def __init__(self):
super().__init__()
def run(self):
print("Starting AuxThread")
self.exec_()
print("Stopping AuxThread")
iteration = 0
# Simulate a long time for thread finish
while iteration < 100:
iteration = 1
print(f"{iteration} cleanup loops in {QThread.currentThread()}")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.thread().setObjectName("main thread")
self.aux_thread = AuxThread()
self.aux_thread.setObjectName("aux thread")
self.aux_thread.start()
def closeEvent(self, event):
print(f"Quitting aux_thread from {QThread.currentThread()}")
self.aux_thread.quit()
# Increasing this time allows the run() function to complete
# If this time is too short, then execution hangs forever
time.sleep(0.001)
print(f"blocking thread {QThread.currentThread()}")
self.aux_thread.wait()
print(f"aux_thread is joined")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Вывод этой функции показан ниже, количество напечатанных итераций будет отличаться в зависимости от времени.
Starting AuxThread
Quitting aux_thread from <PySide2.QtCore.QThread(0x7fcc9cfd12b0, name = "main thread") at 0x11c4f1580>
Stopping AuxThread
1 cleanup loops in <__main__.AuxThread(0x7fcc9cfe5e40, name = "aux thread") at 0x11c4f15c0>
2 cleanup loops in <__main__.AuxThread(0x7fcc9cfe5e40, name = "aux thread") at 0x11c4f15c0>
... [output elided] ...
72 cleanup loops in <__main__.AuxThread(0x7fcc9cfe5e40, name = "aux thread") at 0x11c4f15c0>
73 cleanup loops in <__main__.AuxThread(0x7fcc9cfe5e40, name = "aux thread") at 0x11c4f15c0>
blocking thread <PySide2.QtCore.QThread(0x7fcc9cfd12b0, name = "main thread") at 0x11c4f1580>
В документах говорится, что QThread.wait()
«блокирует поток до тех пор, пока QThread не завершит выполнение (т. Е. Когда он вернется из run()
)»
Интересно, что они не упоминают, какой поток здесь заблокирован, но не имеет смысла блокировать QThread, который вы ожидаете. Я думаю, aux_thread.wait()
следует блокировать только основной поток, почему выполнение во вспомогательном потоке блокируется сразу после wait()
вызова?
Чего мне не хватает?
Комментарии:
1. Вы вызываете
aux_thread.quit()
, поэтому совершенно ясно, какой поток имеется в виду.aux_thread
это не основной поток. Кстати. обычно вы не хотите блокировать основной поток 🙂2.на самом деле, я пытаюсь заблокировать закрытие до
aux_thread
завершения. Вопрос в том, почемуaux_thread.wait()
блокируетсяaux_thread
иmain_thread
3. Это блокирует поток, в котором вызываются
quit
иwait
, в данном случае основной поток. Потому что он ожидает завершения всех ваших операцийaux_thread
. Если нет конкретных результатов, которых вам нужно дождаться, вы могли бы вызвать простоquit
. Он не должен блокироватьaux_thread
, он просто завершается, как только может (если вы имеете в виду, почему он не выводит значение 99).4. Согласно документам,
aux_thread
не должно быть заблокировано. Но в приведенном мной примере она блокируется при моем вызовеaux_thread.wait()
Программа никогда не завершается, она вечно зависает при вызове ожидания