![](/img/trans.png)
[英]How to postpone execution of the QRunnable until signal from previous is emitted
[英]In PyQT how to store data emitted from signal in QRunnable
我在使用Python3的PyQT4应用程序中花了一段时间。 所以我一直在研究使用线程加速它。 数据很容易被破坏并循环处理。 我正在使用自定义QRunnable
,您可以在其中传递目标函数和args,然后将其馈送到QThreadpool
。 我使用pyqtSignal
从每个工作程序中发出处理后的数据。 我的广告位正在接收数据,但未存储数据。 以下是我尝试过的简化示例。
import sys, time
from random import uniform
from PyQt4 import QtCore, QtGui
class AWorker(QtCore.QRunnable):
""" Generic Task for ThreadPool to execute required Kwargs =
target (<function>): function to call
args (tuple): args for target
kwargs (dict): kwargs for target """
def __init__(self, target=None, args=(), kwargs={}):
super(AWorker, self).__init__()
self.target = target
self.args = args
self.kwargs = kwargs
def run(self):
self.target(*self.args, **self.kwargs)
class myTest(QtCore.QObject):
doneSignal = QtCore.pyqtSignal(int) #Create a signal to emit the data
def __init__(self):
super(myTest, self).__init__()
self._procData = [] #Place to Store data .. maybe
self.pool = QtCore.QThreadPool.globalInstance()
self.pool.setMaxThreadCount(4) #Use up to 8 threads
def runAll(self):
self.doneSignal.connect(self.storeData)
for data in range(4):
worker = AWorker(target=self.processData, args=(data,))
self.pool.start(worker)
def processData(self,data):
print('Crunching ...', str(data))
outData = data+10
time.sleep(uniform(1,3)) #Simulate this taking a random amount of time
self.doneSignal.emit(outData)
def storeData(self,data):
print('Received ...', str(data))
self._procData.append(data)
def getData(self):
return self._procData
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
test = myTest()
test.runAll()
test.pool.waitForDone()
print('All done ... and the data is: ',test.getData())
app.exec_()
它会运行,并且从打印输出中可以看到以下内容:
Crunching ... 0
Crunching ... 1
Crunching ... 3
Crunching ... 2
All done ... and the data is: []
Received ... 13
Received ... 11
Received ... 12
Received ... 10
好吧,信号要等到信号全部完成后才发出吗? 也许? 还是因为我在不同的线程中或其他原因而无法分配给_procData
? 我试图删除waitForDone()
只是为了看看,但是按预期没有帮助。
那么,组装每个工人的数据输出的正确方法是什么? 我想提出一个后续问题,即如何确保以正确的顺序放回原位。
我的代码之一遇到了类似的问题(也可能与此问题有关: 从QRunnable发出信号 )。
与您的情况一样,已执行QRunnable
的操作,但结果未添加到结果列表中。 在另一篇文章中的答案说这是因为没有调用主事件循环(使用app.exec_()
类的东西)。 我想在您的情况下是因为您尝试在调用app.exec_()
)之前打印返回的结果(为空)(我可能已经阅读了QThread或QRunnable的事件/信号已排队,或在exec_
调用之前进行了exec_
?即使在您的情况下,也可以从回调函数中打印接收到的每个结果。
我想一个变通可能是创建一个QEventLoop
这将processEvents
从的工人QThreadPool
,那么当它exit()
所有信号/事件被处理。 使用您的代码可能看起来像:
def runAll(self):
self.eventloop = QEventLoop()
self.pool = QtCore.QThreadPool.globalInstance()
self.pool.setMaxThreadCount(4)
self.doneSignal.connect(self.storeData)
for data in range(4):
worker = AWorker(target=self.processData, args=(data,))
self.pool.start(worker)
self.pool.waitForDone()
self.eventloop.processEvents()
self.eventloop.exit()
# Now your data should have been appended to your list
(我没有测试此代码段,但是我对我的某些QThreadPool
成功使用了类似的模式)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.