关于qt:PySide2 QThread错误:QThread:线程仍在运行时被销毁

PySide2 QThread Error: QThread: Destroyed while thread is still running

我是PySide2的新手。 我只是试图启动一个示例应用程序,并在应用程序启动时启动线程,并希望在应用程序关闭时停止线程。 当我关闭应用程序时,出现以下错误:
QThread:在线程仍在运行时被销毁。
sample_ui.py是我从sample_ui.ui转换而来的python文件

码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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_())

输出:

1
2
3
4
5
Thread is Running
Thread is Running
Thread is Running
Thread Stopped
QThread: Destroyed while thread is still running

说明:

默认情况下,QThread run()方法具有以下实现:

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

换句话说,run方法执行事件循环,但是当重写该方法时,您将通过while循环删除事件循环。

另一方面,如果对Qt文档进行了审查:

void QThread::quit()

Tells the thread's event loop to exit with return code 0 (success).
Equivalent to calling QThread::exit(0).

This function does nothing if the thread does not have an event loop.

(强调我的)

因此,如果没有事件循环,那么quit方法将无济于事。

解:

一种可能的解决方案是使用isInterruptionRequested()requestInterruption(),因为第一个指示标志的状态,第二个指示标志的状态。另一方面,您必须等待线程使用wait()方法完成执行:

1
2
3
4
5
6
7
8
9
10
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()将不执行任何操作。您应该使用一个标志来"关闭" run()内部的while,而不是检查QThread::isRunning()返回的内容。此外,建议始终添加具有特定时间限制的QThread::wait(),然后添加(作为备份计划)QThread::terminate()

就像实验一样,在调用stop()函数并查看返回值之后,添加对QThread::isRunning()的检查。