PySide:线程导致GUI崩溃

时间:2015-09-05 01:14:49

标签: multithreading python-3.x pyside

我正在尝试使用PySide学习线程的基础知识,因此将下面的代码放在一起。我尝试做的是启动一个线程,该线程将使用字符串列表更新QPlainTextEdit小部件,每个字符串之间有一个延迟。相反,我得到的是桌面崩溃,我无法理解原因:

import sys
import time

from PySide import QtCore, QtGui

class Worker(QtCore.QThread):

    to_log = QtCore.Signal(str)

    def __init__(self, txt, parent=None):
        super(Worker, self).__init__(parent)

        self.txt = txt

    def run(self):

        for i in self.txt:
            self.to_log.emit(i)
            time.sleep(1)


class TestThreadsApp(QtGui.QWidget):

    def __init__(self):
        super(TestThreadsApp, self).__init__()

        self.initUI()

    def initUI(self):

        self.log = QtGui.QPlainTextEdit()
        self.pb = QtGui.QPushButton('Go')

        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(self.log)
        hbox.addWidget(self.pb)

        self.setLayout(hbox)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Test')
        self.show()

        self.pb.clicked.connect(self.get_worker)

    def get_worker(self):
        self.proceed = False

        worker = Worker(['This is a test', 'to understand threading'])
        worker.to_log.connect(self.to_log)
        worker.start()

    def to_log(self, txt):
        self.log.appendPlainText(txt)

def main():

    app = QtGui.QApplication(sys.argv)
    ex = TestThreadsApp()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

如果我将get_worker()方法更新到下面,它将运行,但QPlainTextEdit小部件会同时更新所有字符串,其中我想要的行为是由小部件更新发出每个字符串时的线程化进程 - 在两个字符串都被发出之后完全没有:

    def get_worker(self):
        self.proceed = False

        worker = Worker(['This is a test', 'to understand threading'])
        worker.to_log.connect(self.to_log)
        worker.start()        

        while not worker.isFinished():
            pass

1 个答案:

答案 0 :(得分:1)

您需要保留对该线程的引用,否则只要get_worker返回就会对其进行垃圾回收。

所以做这样的事情,而不是:

    def get_worker(self):
        self.worker = Worker(['This is a test', 'to understand threading'])
        self.worker.to_log.connect(self.to_log)
        self.worker.start()