簡體   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