为什么在QDialog中发出的信号不能调用QThread中连接的插槽?

时间:2015-03-06 06:20:31

标签: python pyside

这是我的代码:

from PySide import QtCore, QtGui
import sys
import time

class TestThread(QtCore.QThread):

    def __init__(self):
        self.finished_flag = False
        super(TestThread, self).__init__()

    def finished(self):
        print('==========finished function is invoked!=======================')
        self.finished_flag = True

    def run(self):
        while(True): 
            print('thread is running...') 
            time.sleep(1)            
            if self.finished_flag:
                print('thread exist!')
                break


class TestDialog(QtGui.QDialog):
    ForceTermimateSignal = QtCore.Signal()

    def done(self, code):
        print('================dialog done!==================')
        self.ForceTermimateSignal.emit()
        super(TestDialog, self).done(code)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    dlg = TestDialog()
    testThread = TestThread()

    dlg.ForceTermimateSignal.connect(testThread.finished)

    testThread.start()

    dlg.exec_()

    if testThread.isFinished():
        print('thread finished')
    else:
        print('thread is still running!')
        testThread.wait()

这是运行上面的代码然后关闭对话框的结果:

thread is running...
thread is running...
thread is running...
thread is running...
================dialog done!==================
thread is still running!
thread is running...
thread is running...
thread is running...

所以我想知道:为什么发出dlg的ForceTermimateSignal不能调用'完成'对象testThread的功能?

2 个答案:

答案 0 :(得分:0)

当您将信号连接到同一线程中的插槽时,将直接并同步调用插槽。但是当连接是跨线程时,信号将作为事件发布,并且将异步调用插槽。

所以在你的例子中,这一行:

    self.ForceTermimateSignal.emit()

将向对话框的事件队列添加信号事件,然后返回而不直接调用线程的finished时隙。以下一行:

    super(TestDialog, self).done(code)
然后将立即执行

,这将在信号事件有机会被处理之前终止事件循环。

如果用以下代码替换发射线:

   testThread.finished_flag = True

示例应该按预期工作。

答案 1 :(得分:0)

受@ekhumoro的启发,我提到了Signals and Slots Across Threads的QT文档,发现QT中有许多不同的连接类型。了解这些类型,一切都很清楚。

替换上面的代码:

dlg.ForceTermimateSignal.connect(testThread.finished)

使用:

dlg.ForceTermimateSignal.connect(teshThread.finished, type=Qt.DirectConnection)

然后,一切都按预期工作。