我正在使用 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 函数的调用是否在单独的线程中完成并不重要,会遇到相同的行为。
progressValueChanged(int)
正如 Qt progressDialog 示例所暗示的那样,我还尝试了该信号。信号progressValueChanged(int)
仅在图像中的 2 行(第一行和最后一行)中发出。这真的很奇怪,因为在 Qt 进度对话框示例中它是顺利发出的。
我对 Qt 示例进行了一些更改,以在主线程之外的另一个线程中启动 map 函数,在这种情况下它仍然可以正常工作。
问题必须来自其他地方。
也许 GUI 事件循环正在做一些我没想到的事情?我不知道是什么。
我现在将尝试 QtConcurrent::mappedReduced 并报告结果:-)
++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++
它不起作用,只有在“map”函数完成时才调用“reduce”函数。换句话说,它的作用与之前的信号/槽机制相同。
我现在的可能性很低
++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++编辑我回到了一个与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();
...
这个调用是在一个 slot中完成的。
如前所述,它为第 0 行和最后一行发出信号,但不发出任何其他信号。
这不应该完全像 Qt 示例所做的那样吗?