【问题标题】:PySide2 QThread Error: QThread: Destroyed while thread is still runningPySide2 QThread 错误:QThread:在线程仍在运行时被销毁
【发布时间】:2020-05-24 06:00:36
【问题描述】:

我是 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

【问题讨论】:

    标签: qt pyqt pyqt5 pyside2


    【解决方案1】:

    说明:

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

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

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

    另一方面,如果 the 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()
    

    【讨论】:

    • 非常感谢,@eyllanesc。我试过你的方法,它奏效了。我非常感谢您花时间解释 QThread run() 方法。如果您能告诉我一些有关 PySide2 和使用 QtDesigner 的资源或教程,那将是一个很大的帮助。谢谢。
    • @PratikTayshete 1) 如果你想了解更多关于 QThread 的解释,那么你应该阅读文档,如果你没有给我指出一个确切的问题,那么我将无法回答你。 2)使用Qt docs,不知道教程或类似的,我认为谷歌可以成为该类型教程的一个很好的搜索引擎。
    • deleteLater() 方法是否与此有关
    【解决方案2】:

    QThread::quit() 如果您的线程没有事件循环,则不执行任何操作。您应该使用一个标志来“关闭”while 在您的 run() 中,而不是检查 QThread::isRunning() 返回的内容。此外,建议始终添加具有特定时间限制的QThread::wait(),然后添加(作为备用计划)QThread::terminate()

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

    【讨论】:

      最近更新 更多