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

3

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

代码:

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个回答

6

说明:

默认情况下,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文档
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()

非常感谢,@eyllanesc。我尝试了你的方法,它起作用了。我真的很感激你花时间解释QThread run()方法。如果您能告诉我一些关于PySide2和使用QtDesigner的资源或教程,那将是极大的帮助。谢谢。 - Pratik Tayshete
@PratikTayshete 1) 如果你想更详细地了解QThread,那么你应该阅读文档。如果你没有提出具体问题,我将无法回答你。2) 使用Qt文档,不要问我关于教程或类似内容的问题,我认为谷歌可以成为这种类型教程的好搜索引擎。 - eyllanesc
deleteLater() 方法与此有关吗? - greendino

1
如果你的线程没有事件循环,QThread::quit() 就不会起作用。你应该使用一个“关闭”标志来停止 run() 中的 while 循环,而不是检查 QThread::isRunning() 的返回值。此外,建议始终添加一个带有特定时间限制的 QThread::wait(),然后再添加(作为备选计划)QThread::terminate()

只是作为一个实验,在调用 stop() 函数之后添加一个对 QThread::isRunning() 的检查,并查看它返回什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接