问题
I want to use PySide2 Qtcore.Qthread because of Qtcore.Signal, but I end up with this error: 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
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_())
回答1:
Explanation
If you run your code in a CMD/Terminal you will get the following error:
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
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:
- Make a "t" class attribute
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:
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:
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()
回答2:
I found the solution but I don't know why I should do this. the thread should a part of the class.
self.t = Thread()
self.t.done.connect(self.done)
self.t.start()
来源:https://stackoverflow.com/questions/58656311/pyside2-qthread-crash