我正在使用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/

    10-13 00:06