Ошибка PySide2 QThread: QThread: уничтожено, пока поток еще работает - PullRequest
2 голосов
/ 08 февраля 2020

Я новичок в 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 ]

1 голос
/ 08 февраля 2020

Объяснение:

По умолчанию метод QThread run () имеет следующую реализацию:

// https://github.com/qt/qtbase/blob/5.14.1/src/corelib/thread/qthread.cpp#L601
void QThread::run()
{
    (void) exec();
}

Другими словами, метод run выполняет событие l oop, но при переопределении тем методом, которым вы удаляете событие l oop, в то время как l oop.

С другой стороны, если пересмотрен Qt docs :

void QThread :: quit ()

Сообщает событию потока l oop о выходе с кодом возврата 0 (успех). Эквивалентно вызову QThread :: exit (0).

Эта функция ничего не делает, если у потока нет события l oop.

(выделено мной)

Таким образом, если событие l oop отсутствует, метод quit ничего не даст.

Решение:

Возможное решение должен использовать isInterruptionRequested() и requestInterruption(), поскольку первый указывает состояние флага, а второй изменяет состояние этого флага. С другой стороны, вам нужно дождаться завершения потока sh, используя метод 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()
1 голос
/ 08 февраля 2020

QThread::quit() ничего не делает, если у вашего потока нет события l oop. Вы должны использовать флаг, который «выключает» while внутри вашего run() вместо проверки того, что возвращает QThread::isRunning(). Кроме того, рекомендуется всегда добавлять QThread::wait() с указанным c ограничением по времени, а затем добавлять (в качестве плана резервного копирования) QThread::terminate().

Так же, как эксперимент, добавьте проверку для QThread::isRunning() после того, как вы вызовете вашу stop() функцию и посмотрите, что она возвращает.

...