如果将 QThread 创建为局部变量,为什么 QThread 会表现不同
Why the QThread behave different if create it as local variable
如果我将 QThread 创建为局部变量,我发现了一个奇怪的行为。
例如,下面的代码将作为单线程运行,这意味着我需要等待 10 秒,结果就会出来。
但是,如果我将线程从局部变量更改为成员变量,它就会像多线程一样工作。
怎么样?谁能给我一些提示?
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
def run(self):
self.dialog.show()
sys.exit(self.app.exec_())
def btnclick(self):
## if change to self.thread, the behavior changes!!
signal = QtCore.SIGNAL("Log(QString)")
thread = testThread(signal)
QtCore.QObject.connect(thread, signal, self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QThread):
def __init__(self, signal):
QThread.__init__(self)
self.signal = signal
def __del__(self):
self.wait()
def run(self):
for i in range(10):
time.sleep(1)
self.output(str(i))
def output(self, txt):
self.emit(self.signal, txt)
if __name__ == "__main__":
ui = UI()
ui.run()
要指出的问题是,它是一个局部变量,会在启动 QThread
后立即销毁,因此 QThread
处理的线程(QThread 不是线程,它是一个线程处理程序)将被删除,当使用 wait()
时,预计 run()
方法将被执行,但在生成 GUI 的主线程中冻结。
所以解决方案是延长可变线程的寿命,您指出它有效的一种方法:使其成为 class 的成员,但还有另一种方法仅适用于 QObjects 作为QThread,即传递一个父对象(父对象必须是另一个QObject),将对象的寿命延长到与父对象相同的容量,因此我将使用对话框。
最后,现在不建议动态创建信号,最好将其创建为 class 的一部分,同时对于连接,您必须使用 the new syntax。
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
self.dialog.show()
def btnclick(self):
thread = testThread(self.dialog)
thread.signal.connect(self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QtCore.QThread):
signal = QtCore.pyqtSignal(str)
def __del__(self):
self.wait()
def run(self):
for i in range(10):
QtCore.QThread.sleep(1)
self.output(str(i))
def output(self, txt):
self.signal.emit(txt)
if __name__ == '__main__':
ui = UI()
app = QtGui.QApplication.instance()
if app is not None:
sys.exit(app.exec_())
如果我将 QThread 创建为局部变量,我发现了一个奇怪的行为。
例如,下面的代码将作为单线程运行,这意味着我需要等待 10 秒,结果就会出来。
但是,如果我将线程从局部变量更改为成员变量,它就会像多线程一样工作。
怎么样?谁能给我一些提示?
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
def run(self):
self.dialog.show()
sys.exit(self.app.exec_())
def btnclick(self):
## if change to self.thread, the behavior changes!!
signal = QtCore.SIGNAL("Log(QString)")
thread = testThread(signal)
QtCore.QObject.connect(thread, signal, self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QThread):
def __init__(self, signal):
QThread.__init__(self)
self.signal = signal
def __del__(self):
self.wait()
def run(self):
for i in range(10):
time.sleep(1)
self.output(str(i))
def output(self, txt):
self.emit(self.signal, txt)
if __name__ == "__main__":
ui = UI()
ui.run()
要指出的问题是,它是一个局部变量,会在启动 QThread
后立即销毁,因此 QThread
处理的线程(QThread 不是线程,它是一个线程处理程序)将被删除,当使用 wait()
时,预计 run()
方法将被执行,但在生成 GUI 的主线程中冻结。
所以解决方案是延长可变线程的寿命,您指出它有效的一种方法:使其成为 class 的成员,但还有另一种方法仅适用于 QObjects 作为QThread,即传递一个父对象(父对象必须是另一个QObject),将对象的寿命延长到与父对象相同的容量,因此我将使用对话框。
最后,现在不建议动态创建信号,最好将其创建为 class 的一部分,同时对于连接,您必须使用 the new syntax。
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
self.dialog.show()
def btnclick(self):
thread = testThread(self.dialog)
thread.signal.connect(self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QtCore.QThread):
signal = QtCore.pyqtSignal(str)
def __del__(self):
self.wait()
def run(self):
for i in range(10):
QtCore.QThread.sleep(1)
self.output(str(i))
def output(self, txt):
self.signal.emit(txt)
if __name__ == '__main__':
ui = UI()
app = QtGui.QApplication.instance()
if app is not None:
sys.exit(app.exec_())