【发布时间】:2016-02-06 02:35:08
【问题描述】:
我有一个使用 Python3 的 PyQT4 应用程序需要一段时间的过程。所以我一直在研究使用线程来加速它。数据很容易被破坏部分并在循环中处理。我正在使用自定义QRunnable,您可以在其中传递目标函数和参数,然后将其输入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() 只是为了看看,但正如预期的那样没有帮助。
那么,组装每个工人的数据输出的正确方法是什么?我想一个后续问题,你如何确保它以正确的顺序放回。
【问题讨论】:
-
在我看来 QThreadPool.waitForDone 实际上并没有等待。全部完成后,您可以看到收到的正在打印。此外,如果您在每个
storeData调用中打印出_procData,您可以看到它实际上是在存储数据。例如Received ... 10 [13, 11, 12, 10] -
我明白你的意思。但是,我仍然不确定 waitForDone 是否不起作用,或者它是否阻塞了信号,直到等待完成完成。任何一个都会给出我认为的相同行为。如果您注释掉等待完成行,您会得到不同的打印输出顺序,其中一些“已接收”与“紧缩”混合,但“全部完成”行仍然是空白的。如果 waitForDone 没有做任何事情,那么无论哪种方式我都希望得到相同的输出。