python - 如何跨线程发送无信号?

标签 python multithreading pyqt pyside signals-slots

我已经实现了 Qt Threading docs 中描述的工作模式版本。 .

我使用信号/槽在工作线程和主线程之间发送数据。

在定义Signal时,我已将参数签名类型设置为object,因为我相信它应该允许我通过Signal传递任何Python对象.

result_ready = QtCore.Signal(object)

但是,当我尝试通过 Signal 传递 None 时,它会使 python 崩溃。仅当尝试跨线程传递Signal时才会发生这种情况。如果我注释掉 self.worker.moveToThread(self.thread) 行,它就会起作用,并且 None 成功通过 Signal

为什么我在这种情况下无法传递 None

我正在使用 PySide 1.2.2Qt 4.8.5

import sys

from PySide import QtCore, QtGui


class Worker(QtCore.QObject):

    result_ready = QtCore.Signal(object)

    @QtCore.Slot()
    def work(self):
        print 'In Worker'

        # This works
        self.result_ready.emit('Value')

        # This causes python to crash
        self.result_ready.emit(None)


class Main(QtGui.QWidget):

    def __init__(self):
        super(Main, self).__init__()
        self.ui_lay = QtGui.QVBoxLayout()
        self.setLayout(self.ui_lay)
        self.ui_btn = QtGui.QPushButton('Test', self)
        self.ui_lay.addWidget(self.ui_btn)
        self.ui_lay.addStretch()
        self.setGeometry(400, 400, 400, 400)
        self.worker = Worker()
        self.thread = QtCore.QThread(self)
        self.worker.moveToThread(self.thread)
        self.thread.start()
        self.ui_btn.clicked.connect(self.worker.work)
        self.worker.result_ready.connect(self.handle_worker_result)

    @QtCore.Slot(object)
    def handle_worker_result(self, result=None):
        print 'Handling output', result

    def closeEvent(self, event):
        self.thread.quit()
        self.thread.wait()
        super(Main, self).closeEvent(event)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    obj = Main()
    obj.show()
    app.exec_()

最佳答案

这看起来像一个 PySide 错误。相同的示例代码在 PyQt4 中的工作方式与预期完全一样。

问题出在 type of signal connection 。对于跨线程信号,除非您另外指定,否则将使用 QueuedConnection。如果示例代码中的连接类型更改为 DirectConnection,它将按预期工作 - 但当然它不再是线程安全的。

QueuedConnection 会将事件发布到接收线程的事件队列。但为了使其线程安全,Qt 必须序列化发出的参数。然而,PySide 显然需要在这里注入(inject)一些魔法来处理 Qt 不了解的 python 类型。如果我不得不猜测,我敢打赌 PySide 错误地将 python None 对象转换为 C++ NULL 指针,这显然会在以后产生严重的后果。

如果您想解决这个问题,我想您可以发出自己的哨兵对象作为 None 的占位符。

更新:

发现错误,PYSIDE-17 ,发布于 2012 年 3 月!遗憾的是,建议的补丁似乎从未经过审查。

关于python - 如何跨线程发送无信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35712870/

相关文章:

python - 如何使 python 文件可作为脚本运行并作为包导入?

c - 在多线程程序中为 system() 向下传递信息

python - 与队列一起使用时 "threads"列表变量的用途是什么

python - 替代 redis.keys(...)

python - 如何将 'google.cloud.documentai.v1beta2.types.document.Document' 转换为 JSON?

c - 服务器从多个客户端接收数据并在Linux中使用C通过线程同时存储在单独的文件中

java - 使用 C3P0 和 Hibernate/Spring 创建的许多线程

python - 单击时如何获取 QMenu 项的名称?

python - 如何重置 QGridLayout 中小部件的列跨度?

python - 张量板 : No dashboards active for current dataset