我已经实现了Qt Threading docs。
中描述的工作模式的一个版本我正在使用Signals/Slots
在工作线程和主线程之间发送数据。
定义Signal
时,我将参数签名类型设置为object
,因为我认为它应该允许我通过Signal
传递任何python对象。
result_ready = QtCore.Signal(object)
然而,当我尝试通过None
传递Signal
时,它会崩溃python。只有在尝试跨线程传递Signal
时才会发生这种情况。如果我发表了self.worker.moveToThread(self.thread)
行的评论,那就行了,None
已成功通过Signal
。
为什么我无法在此实例中传递None
?
我正在使用PySide 1.2.2
和Qt 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_()
答案 0 :(得分:2)
这看起来像是一个PySide错误。相同的示例代码与PyQt4完全一样。
问题在于type of signal connection。对于跨线程信号,除非另行指定,否则将使用QueuedConnection
。如果示例代码中的连接类型更改为DirectConnection
,它将按预期工作 - 但当然它不再是线程安全的。
QueuedConnection
会将事件发布到接收线程的事件队列。但为了使其成为线程安全的,Qt必须序列化发出的参数。但是,PySide显然需要在这里注入一些魔法来处理Qt对此一无所知的python类型。如果我不得不猜测,我敢打赌PySide错误地将python None
对象转换为C ++ NULL指针,这显然会在以后产生令人讨厌的后果。
如果你想解决这个问题,我想你可以发布你自己的哨兵对象作为None
的占位符。
<强>更新强>:
发现了2012年3月发布的错误PYSIDE-17!可悲的是,建议的补丁似乎从未被审查过。
答案 1 :(得分:1)
如果你改变信号到适当的班级,那么它对我来说很好。例如:
result_ready = QtCore.Signal(str)
这适用于两种情况。
根据文件
可以使用QtCore.Signal()类定义信号。 Python类型和C类型可以作为参数传递给它。如果你需要重载它,只需将类型作为元组或列表传递。
https://wiki.qt.io/Signals_and_Slots_in_PySide#Using_QtCore.Signal.28.29