PySide2 Qthread 崩溃

Posted

技术标签:

【中文标题】PySide2 Qthread 崩溃【英文标题】:PySide2 Qthread crash 【发布时间】:2019-11-01 08:43:16 【问题描述】:

由于 Qtcore.Signal,我想使用 PySide2 Qtcore.Qthread,但我最终得到了这个错误: 进程以退出代码 -1073740791 结束

from PySide2.QtCore import QThread


class Thread(QThread):
    def run(self):
        print('task started')
        k = 0
        for i in range(10000):
            for j in range(5000):
                k += 1
        print('task finished')

Thread().start()

希望有这些打印,但我有这个错误:

进程以退出代码 -1073740791 结束

更新:

那么,为什么这段代码也会抛出同样的错误?

class Thread(QThread):
    done = Signal()

    def __init__(self):
        super(Thread, self).__init__()

    def run(self):
        print('task started')
        k = 0
        for i in range(10000):
            for j in range(5000):
                k += 1
        print('task finished')
        self.done.emit()

class Widget(QtWidgets.QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        btn = QtWidgets.QPushButton('test', parent=self)
        btn.clicked.connect(self.clicked)
        btn.show()

    def clicked(self):
        t = Thread()
        t.done.connect(self.done)
        t.start()

    def done(self):
        print('done')

app = QtWidgets.QApplication()
window = Widget()
window.show()
sys.exit(app.exec_())

【问题讨论】:

【参考方案1】:

说明

如果您在 CMD/终端中运行代码,您将收到以下错误:

QThread: Destroyed while thread is still running
Aborted (core dumped)

这个错误是因为线程在运行时被销毁,因为它是一个局部变量,另一方面QThread需要一个事件循环来运行

解决方案

import sys
from PySide2.QtCore import QCoreApplication, QThread


class Thread(QThread):
    def run(self):
        print("task started")
        k = 0
        for i in range(10000):
            for j in range(5000):
                k += 1
        print("task finished")


if __name__ == "__main__":
    # create event loop
    app = QCoreApplication(sys.argv)

    th = Thread()
    th.start()

    th.finished.connect(QCoreApplication.quit)
    sys.exit(app.exec_())

更新:

"t" 是一个局部变量,执行 clicked 后将被消除,导致与初始代码相同的问题,解决方案是防止它立即被破坏,为此有 2 个选项:

创建一个“t”类属性
def clicked(self):
    self.t = Thread()
    self.t.done.connect(self.done)
    self.t.start()
将 QThread 存储在具有更长生命周期的容器中:
class Widget(QtWidgets.QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        btn = QtWidgets.QPushButton('test', parent=self)
        btn.clicked.connect(self.clicked)

        self.container = []

    def clicked(self):
        t = Thread()
        t.done.connect(self.done)
        t.start()
        self.container.append(t)

    # ...
将其作为父级传递给“self”,但为此线程必须允许接收,因此您必须在构造函数中实现它:
class Thread(QThread):
    done = Signal()

    def __init__(self, parent=None):
        super(Thread, self).__init__(parent)

    # ...
def clicked(self):
    t = Thread(self)
    t.done.connect(self.done)
    t.start()

【讨论】:

我更新了问题,用你的方法我做了一个 QApplication 和小部件,但它又抛出了同样的错误! @SaeidGholizade 如果我的回答对您有所帮助,请不要忘记标记为正确,如果您不知道该怎么做,请查看tour【参考方案2】:

我找到了解决方案,但我不知道为什么要这样做。线程应该是类的一部分。

self.t = Thread()
self.t.done.connect(self.done)
self.t.start()

【讨论】:

我在我的回答中指出了同样的问题,并解释了问题的原因。

以上是关于PySide2 Qthread 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

PySide2 QThread 正在冻结 UI

PyQt5 与 QThread 崩溃

无法关闭 QThread - 应用程序崩溃

也许 QThread 中的 QTLineEdit 范围会导致程序崩溃?

为啥在 macOS 上使用 QThread 时 PyQt 应用程序崩溃或挂起?

如何使用 QThread 进行子线程之间的数据传输?