当我在下面的'minimal'示例中将启动QThread的函数更改为'_do_print2'时,我的MainWindow会冻结。对于比较,上面的按钮将启动QThread而没有任何问题。为什么线程是MainWindow类的子对象?
我正在使用Python 2.7.6和Qt 4.8.6。
from PyQt4 import QtCore, QtGui
import sys, time
class MainWindow(QtGui.QDialog):
def __init__(self):
super(self.__class__, self).__init__()
self.verticalLayout = QtGui.QVBoxLayout(self)
self.pushButton = QtGui.QPushButton()
self.pushButton2 = QtGui.QPushButton()
self.verticalLayout.addWidget(self.pushButton)
self.verticalLayout.addWidget(self.pushButton2)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL('clicked()'), self._do_print)
QtCore.QObject.connect(self.pushButton2, QtCore.SIGNAL('clicked()'), self._do_print2)
## Working function
def _do_print(self):
self.thread = Worker(printer)
self.thread.start()
## Function freezes the MainWindow
def _do_print2(self):
thread = Worker(printer)
thread.start()
def printer():
while True:
print "alive"
time.sleep(1)
class Worker(QtCore.QThread):
def __init__(self, function, *args, **kwargs):
super(self.__class__, self).__init__()
self.args = args
self.kwargs = kwargs
self.function = function
def run(self):
self.function(*self.args, **self.kwargs)
return
def __del__(self):
self.wait()
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
答案 0 :(得分:1)
剧本"冻结"因为你告诉它要做到这一点。
Worker
类定义了__del__
方法,这使得线程等待(或者#34;冻结"如你所说),直到run方法返回。但是它当然永远不会返回,因为它调用的函数启动一个永不终止的阻塞循环。调用__del__
方法是因为您没有保留对线程的引用,因此只要_do_print2()
方法返回(即在线程启动后立即),它就会被垃圾收集。
请注意,第一个线程不是主窗口的子 - 它只是一个实例属性(这使它保持活动状态)。如果删除__del__
方法,启动第二个线程可能会使程序崩溃,因为没有什么可以阻止底层C ++线程过早删除。