如果线程不是主线程的子对象,为什么我的Qt应用程序会冻结?

时间:2016-04-03 12:17:34

标签: python multithreading qt

当我在下面的'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_())

1 个答案:

答案 0 :(得分:1)

剧本"冻结"因为你告诉它要做到这一点。

Worker类定义了__del__方法,这使得线程等待(或者#34;冻结"如你所说),直到run方法返回。但是它当然永远不会返回,因为它调用的函数启动一个永不终止的阻塞循环。调用__del__方法是因为您没有保留对线程的引用,因此只要_do_print2()方法返回(即在线程启动后立即),它就会被垃圾收集。

请注意,第一个线程不是主窗口的 - 它只是一个实例属性(这使它保持活动状态)。如果删除__del__方法,启动第二个线程可能会使程序崩溃,因为没有什么可以阻止底层C ++线程过早删除。