我正在使用QtConcurrent进行一些繁重的背景图像处理,并且我想在图像的某些部分逐渐更新的同时显示该图像。
图像的每一行都是单独计算的,并传递给仿函数。
为了计算完整图像,我需要映射一系列的项目,并将其传递给QtConcurrent,并且每行完成计算后都会发出信号
这是Worker类的实例化:
//living in the main(gui) thread !
Worker::Worker(VideoEngine* engine):_engine(engine){
_watcher = new QFutureWatcher<bool>;
_watcher->setPendingResultsLimit(200);
connect(_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(onProgressUpdate(int)));
connect(_watcher, SIGNAL(finished()), engine, SLOT(engineLoop()));
}
这是报告进度的位置:
void Worker::onProgressUpdate(int i){
if(i < (int)_rows.size() && i%10==0){
cout << " index = " << i << " y = "<< _rows[i] << endl;
_engine->checkAndDisplayProgress(_rows[i],i);
}
}
现在的用法:
void Worker::_computeTreeForFrame(.../*unrelevant args*/){
....
....
_watcher->setFuture(
QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output)));
}
}
所有信号都被发射,但是只有在序列中的所有项目都完成Qtconcurrent::mapped时,插槽onProgressUpdate才被调用。
当执行时,在处理序列时会有很大的延迟,然后所有的插槽随后都将顺序执行。
我尝试了所有类型的信号/插槽连接,但没有一个改变这种行为。
有什么线索吗?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在Shf建议之后进行编辑
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
到目前为止,该调用是在main(gui)线程中进行的。
我将通话更改为:
_computeFrameWatcher->setFuture(QtConcurrent::run(_worker,&Worker::computeTreeForFrame));
由于
_computeTreeForFrame
现在在另一个线程中执行,因此我将对QtConcurrent::mapped的调用更改为:_watcher->setFuture(QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output)));
_watcher->waitForFinished();
这将导致与以前完全相同的行为。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Marek R建议后进行编辑
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
好的,所以我做了这样的测试,这是我观察到的:
QtConcurrent::map:
resultReadyAt(int)
QtConcurrent::mapped
resultReadyAt(int)
对map函数的调用是否在单独的线程中完成也没关系,这与遇到相同的行为无关。
我还尝试了Qt progressDialog示例所建议的
progressValueChanged(int)
信号。信号
progressValueChanged(int)
仅在图像中的两行(第一个和最后一个)中发出。这真的很奇怪,因为在Qt进度对话框示例中,它发出得很顺利。
我对Qt示例进行了一些更改,以在除主线程之外的另一个线程中启动map函数,在这种情况下它仍然运行良好。
该问题必须来自其他地方。
也许GUI事件循环正在做我不期望的事情?我不知道什么。
我现在将尝试QtConcurrent::mappedReduced并报告结果:-)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
尝试QtConcurrent::mappedReduced后进行编辑
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
它不起作用,仅在完成“ map ”功能后才调用“减少”功能。换句话说,它的功能与以前的信号/插槽机制相同。
我现在的可能性很低
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
编辑我回到Qt进度对话框示例附近的解决方案
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
如果我无法获得与Qt示例相同的行为,那一定是错误的。
现在是下面的代码:
//created in the main thread! (gui)
Worker::Worker(VideoEngine* engine):_engine(engine),_watcher(0){
_watcher = new QFutureWatcher<void>;
_watcher->setPendingResultsLimit(200);
connect(_watcher,SIGNAL(progressValueChanged(int)), _engine,
SLOT(onProgressUpdate(int)));
connect(_watcher, SIGNAL(finished()), engine, SLOT(engineLoop()));
}
//executed on the main thread
void Worker::computeTreeForFrame(...){
...
_watcher->setFuture(QtConcurrent::map(_sequence,boost::bind(metaEnginePerRow,_1,output)));
...
}
调用computeTreeForFrame ...
...
_worker->computeTreeForFrame();
...
此调用在插槽中进行。
如前所述,它为第0行和最后一行发出信号,但不发出其他任何信号。
这不应该完全像Qt示例那样吗?
最佳答案
从任务描述看来,您应该使用mappedReduced。问题是我看不到获得部分结果的好方法。克服此问题的一种方法是发出信号形式的缩减功能。
this thread可能会有所帮助。
关于c++ - QtConcurrent映射和进度报告,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18527473/