为啥我不能在类的成员函数中初始化 QThread?
Posted
技术标签:
【中文标题】为啥我不能在类的成员函数中初始化 QThread?【英文标题】:Why can't I initialize a QThread in a member function of class?为什么我不能在类的成员函数中初始化 QThread? 【发布时间】:2014-09-20 15:46:22 【问题描述】:代码如下:
##########################################################
######## Version 1 (works)
##########################################################
#!/usr/bin/env python3
from ui.qthreadtest import Ui_QthreadTest
from PySide import QtCore, QtGui
import time
class Md(QtGui.QDialog):
def __init__(self):
super().__init__()
self.prcsbtn = QtGui.QPushButton("Process")
self.prcsedit = QtGui.QLineEdit()
layout = QtGui.QHBoxLayout()
layout.addWidget(self.prcsedit)
layout.addWidget(self.prcsbtn)
self.setLayout(layout)
self.prcsbtn.clicked.connect(self.work)
self.wt = Worker()
def work(self):
self.wt.start()
# the DirectConnection option demands the slot to be triggered immediately
self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)
def changeText(self):
self.prcsedit.setText("Work finished!")
class Worker(QtCore.QThread):
workFinished = QtCore.Signal()
def __init__(self):
super().__init__()
def run(self):
time.sleep(2)
self.workFinished.emit()
import sys
app = QtGui.QApplication(sys.argv)
md = Md()
md.show()
sys.exit(app.exec_())
##########################################################
######## Version 2 (doesn't work)
##########################################################
#!/usr/bin/env python3
from ui.qthreadtest import Ui_QthreadTest
from PySide import QtCore, QtGui
import time
class Md(QtGui.QDialog):
def __init__(self):
super().__init__()
self.prcsbtn = QtGui.QPushButton("Process")
self.prcsedit = QtGui.QLineEdit()
layout = QtGui.QHBoxLayout()
layout.addWidget(self.prcsedit)
layout.addWidget(self.prcsbtn)
self.setLayout(layout)
self.prcsbtn.clicked.connect(self.work)
def work(self):
# the worker thread initialized in a member function won't work.
wt = Worker()
wt.start()
# the DirectConnection option demands the slot to be triggered immediately
wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)
def changeText(self):
self.prcsedit.setText("Work finished!")
class Worker(QtCore.QThread):
workFinished = QtCore.Signal()
def __init__(self):
super().__init__()
def run(self):
time.sleep(2)
self.workFinished.emit()
import sys
app = QtGui.QApplication(sys.argv)
md = Md()
md.show()
sys.exit(app.exec_())
版本 1 工作正常,版本 2 出现此错误(按下 Process 按钮时会立即崩溃):
QThread: Destroyed while thread is still running
Process finished with exit code 139
【问题讨论】:
错误消息几乎没有让事情变得更明显,特别是因为这两个示例之间唯一真正的区别是一个保持对工作线程的引用,而另一个没有。此外,您应该注意使用direct connection for the signal is not safe。 【参考方案1】:发生这种情况是因为与threading.Thread
对象不同,QThread
对象一旦超出范围就会被销毁。在您的示例中,wt
在work
结束时超出范围,因此对象被销毁。为避免这种情况,您需要保持对wt
的持久引用。一种方法是使其成为实例变量:
def work(self):
self.wt = Worker()
self.wt.start()
# the DirectConnection option demands the slot to be triggered immediately
self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)
【讨论】:
以上是关于为啥我不能在类的成员函数中初始化 QThread?的主要内容,如果未能解决你的问题,请参考以下文章
为啥不能在派生类的构造函数初始化列表中初始化基类的数据成员?