简体   繁体   English

PySide2 Qthread 崩溃

[英]PySide2 Qthread crash

I want to use PySide2 Qtcore.Qthread because of Qtcore.Signal, but I end up with this error: Process finished with exit code -1073740791由于Qtcore.Signal,我想使用PySide2 Qtcore.Qthread,但最终出现此错误: Process finished with exit code -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()

expect to have those prints but I have this error:期望有这些打印,但我有这个错误:

Process finished with exit code -1073740791进程以退出代码 -1073740791 结束

Update:更新:

so, why this code also throw the same error?那么,为什么这段代码也会抛出同样的错误呢?

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_())

Explanation解释

If you run your code in a CMD/Terminal you will get the following error:如果您在 CMD/终端中运行代码,您将收到以下错误:

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

And the error is caused because the thread is destroyed while it is still running since it is a local variable, on the other hand QThread needs an event loop to run错误是因为线程在运行时被销毁,因为它是一个局部变量,另一方面 QThread 需要一个事件循环来运行

Solution解决方案

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_())

Update:更新:

"t" is a local variable that will be eliminated after executing clicked causing the same problem as your initial code, the solution is to prevent it from being destroyed instantly and for this there are 2 options: “t”是一个局部变量,在执行 clicked 后将被消除,导致与初始代码相同的问题,解决方案是防止它立即被破坏,为此有 2 个选项:

  • Make a "t" class attribute创建一个“t”class 属性
def clicked(self):
    self.t = Thread()
    self.t.done.connect(self.done)
    self.t.start()
  • Store the QThread in a container that has a longer life cycle:将 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)

    # ...
  • Pass it as a parent to "self" but for this it is necessary that Thread allow to receive so you must implement that in the constructor:将其作为父级传递给“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()

I found the solution but I don't know why I should do this.我找到了解决方案,但我不知道为什么要这样做。 the thread should a part of the class.线程应该是 class 的一部分。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM