gpt4 book ai didi

qt - PySide 插槽不在对象的线程中运行

转载 作者:行者123 更新时间:2023-12-04 14:25:32 31 4
gpt4 key购买 nike

我试图在 PySide 的单独线程中运行一个长任务,以便主线程可以继续处理 GUI 事件。我已经阅读了执行此操作的正确方法:

  • 将任务封装在 QObject 子类中,其中工作在 run() 方法中完成,并在完成时发出 finished 信号。
  • 创建一个新的 QThread 并使用 QObject.moveToThread() 设置任务对象的线程关联。
  • 将线程的 start 信号连接到任务的 run() 方法。
  • 使用 QThread.start() 启动线程。

但是,我遇到了一个奇怪的问题,如果 run() 方法被包装在一个槽中,该函数将在主线程而不是对象所属的线程中运行.如果我将其保留为标准 Python 方法,一切正常。

这是我创建的一个最小示例:

#!/usr/bin/env python

import sys

from PySide import QtCore, QtGui


class Task(QtCore.QObject):
"""Does some work and emits a signal when done."""

finished = QtCore.Signal(object)

def run1(self):
"""Runs task and emits finished() signal when done."""
try:
# Try running the task
result = self._run()

except:
self.finished.emit(None)

else:
self.finished.emit(result)

@QtCore.Slot()
def run2(self):
"""Same as run1, but wrapped in a slot."""
self.run1()

def _run(self):
"""Override in subclass"""
pass


class TestTask(Task):
"""Prints thread ID."""

def __init__(self, name):
super().__init__()
self.name = name

def _run(self):
print('{} thread ID:'.format(self.name), QtCore.QThread.currentThreadId())
return 'success'


def main():

gui = QtGui.QApplication([])

print('Main thread ID: ', QtCore.QThread.currentThreadId())

# thread1 calls task1.run1()
task1 = TestTask('task1')
task1.finished.connect(lambda r: print('Task 1 finished:', r))

thread1 = QtCore.QThread()
task1.moveToThread(thread1)

thread1.started.connect(task1.run1)

# thread2 calls task2.run2()
task2 = TestTask('task2')
task1.finished.connect(lambda r: print('Task 2 finished:', r))

thread2 = QtCore.QThread()
task2.moveToThread(thread2)

thread2.started.connect(task2.run2)

# Start both threads
thread1.start()
thread2.start()

# Run event loop (doesn't actually return)
sys.exit(gui.exec_())


if __name__ == '__main__':
main()

这会产生以下输出:

Main thread ID:  139962303178496
task1 thread ID: 139961642776320
task2 thread ID: 139962303178496
Task 2 finished success
Task 1 finished success

run() 保留为标准 Python 方法没什么大不了的,但我想知道为什么会这样。这是 QT4.8 和 PySide 1.2.4。

最佳答案

这可能是由 PySide 中的一个可能错误引起的。该问题似乎是由继承具有装饰插槽的基类引起的。如果这个插槽被移动到子类中,问题就消失了:

class TestTask(Task):
...

@QtCore.Slot()
def run2(self):
"""Same as run1, but wrapped in a slot."""
self.run1()

(PS:作为另一个数据点,值得注意的是您的原始示例在 PyQt4 中运行良好)。

更新:

据推测,这是由 PySide 中的一个已知错误引起的:请参阅 PYSIDE-249 .

关于qt - PySide 插槽不在对象的线程中运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45767497/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com