繁体   English   中英

在PyQT中如何将信号发射的数据存储在QRunnable中

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM