Я новичок в PySide2. Я просто пытаюсь запустить пример приложения и запустить поток при запуске приложения и хочу остановить поток при закрытии приложения. Когда я закрываю приложение, я получаю следующую ошибку: QThread: уничтожено во время работы потока. Sample_ui.py - это файл Python, который я преобразовал из sample_ui.ui
Код:
import time
import sys
import sample_ui
from PySide2 import QtWidgets
from PySide2 import QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
main_window_ui = sample_ui.Ui_MainWindow()
main_window_ui.setupUi(self)
self.custom_thread = CustomThread()
self.custom_thread.start()
def closeEvent(self, event):
self.custom_thread.stop()
QtWidgets.QMainWindow.closeEvent(self, event)
class CustomThread(QtCore.QThread):
def __init__(self):
super(CustomThread, self).__init__()
def run(self):
while self.isRunning():
print("Thread is Running")
time.sleep(1)
def stop(self):
print("Thread Stopped")
self.quit()
if __name__ == '__main__':
app = QtWidgets.QApplication()
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Выход:
Thread is Running
Thread is Running
Thread is Running
Thread Stopped
QThread: Destroyed while thread is still running
Всего 2 ответа
По умолчанию метод QThread run () имеет следующую реализацию:
// https://github.com/qt/qtbase/blob/5.14.1/src/corelib/thread/qthread.cpp#L601
void QThread::run()
{
(void) exec();
}
Другими словами, метод run выполняет цикл событий, но при переопределении этого метода вы удаляете цикл событий с помощью цикла while.
С другой стороны, если Qt docs просматривается:
void QThread :: quit ()
Сообщает о выходе из цикла потока с кодом возврата 0 (успех). Эквивалентно вызову QThread :: exit (0).
Эта функция ничего не делает, если у потока нет цикла обработки событий .
(акцент мой)
Так что если нет никакого цикла обработки событий, то метод quit ничего не сделает.
Возможное решение состоит в том, чтобы использовать isInterruptionRequested()
и requestInterruption()
так как первый указывает состояние флага, а второй изменяет состояние этого флага. С другой стороны, вам нужно дождаться окончания выполнения потока с помощью метода wait()
:
class CustomThread(QtCore.QThread):
def run(self):
while not self.isInterruptionRequested():
print("Thread is Running")
time.sleep(1)
def stop(self):
print("Thread Stopped")
self.requestInterruption()
self.wait()
QThread::quit()
ничего не делает, если у вашего потока нет цикла обработки событий. Вы должны использовать флаг, который «отключает» в while
время while
внутри вашего run()
вместо проверки того, что QThread::isRunning()
. Кроме того, рекомендуется всегда добавлять QThread::wait()
с определенным ограничением времени, а затем добавлять (в качестве плана резервного копирования) QThread::terminate()
.
В качестве эксперимента добавьте проверку для QThread::isRunning()
после вызова функции stop()
и посмотрите, что она возвращает.