我正在构建一个带有 GUI 和几个工作线程的应用程序。现在我希望它是一个多线程应用程序,所以我在一个循环中多次执行同一个线程,每个线程获取线程外部类中定义的不同输入参数。
所以我的 mainGui.py 文件看起来像这样(仅显示相关代码):
self.workers = [worker.Worker(), worker.Worker(), worker.Worker()]
for i in xrange(threadCount):
self.currentWorker = self.workers[i]
self.currentWorker.alterTable.connect(self.alterMainTable)
self.currentWorker.start()
time.sleep(0.1)
正如您可能想象的那样,我将 Worker 的alterTable
信号连接到alterMainTable()
我在主 GUI 线程中定义的方法。此方法更新 GUI 中的表。
工作线程看起来像这样:
class Worker(QThread):
alterTable = Signal(dict)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
def sendToTable(self, param1, param2, param3):
"""This method emits the signal with params as defined above"""
params = {}
params["param1"] = param1
params["param2"] = param2
params["param3"] = param3
self.alterTable.emit(params)
def run(self):
#Perform a lengthy task, do this every now and then:
self.sendToTable(param, param2, param3)
当我在单个工作线程中运行此应用程序时(所以当我不在主线程中调用该循环时),它工作正常 - 发出信号,并更新 GUI 中的主表。
但是,当我一次运行多个线程时会出现问题。Worker 线程完成他们的工作,但有时只会发出 Signal。或者,更好的是,它就像 Qt(或其他)正在等待所有线程完成,然后更新表一样发出。这就是实际发生的情况——我可以在 Python 控制台中看到线程正在执行它们的任务,一旦它们都在做它们正在做的任何事情,表格就会突然立即填充一堆数据。
正如您可能想象的那样,由此产生的另一个问题是,由于没有正在处理的事件,一段时间后,我的应用程序似乎被冻结了。
我已经尝试将其添加Qt.DirectConnection
到该connect()
方法中,但这并没有真正帮助。
额外问题:我一直在 SO 和其他网站上阅读有关此主题的内容,似乎人们推荐QRunnable()
而不是QThread()
特别推荐子类化它。因此,我会使用QThreadPool()
. 但是当我尝试这个时,似乎我无法从 a 发出信号QRunnable
- 它给了我AttributeError: 'PySide.QtCore.Signal' object has no attribute 'connect'
,即使 Signal 是在 QRunnable 类中定义的 - 这很奇怪,我必须说。
编辑:在关于 SO 的另一个答案中,有人提到可能正在向主 GUI 线程“发送垃圾邮件”,其中包含要处理的事件。但是,我不相信这是这种情况,因为sendToTable()
来自 QThread 的方法最多只从线程调用 5-6 次,并且最多threadCount
不大于 20,但我通常将其保持在 5 左右.