11

如果我正确理解了 QFutureWatcher 文档中的以下代码,则最后一行之间存在竞争条件:

// Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));

// Start the computation.
QFuture<int> future = QtConcurrent::run(...);
watcher.setFuture(future);

如果函数...在下QtConcurrent::run(...)一行被调用之前完成,那么watcher.finished()信号将永远不会被触发。我的假设正确吗?如何解决此错误?

4

2 回答 2

13

来自http://doc.qt.io/qt-4.8/qfuturewatcher.html#setFuture

可能会针对未来的当前状态发出其中一个信号。例如,如果未来已经停止,将发出完成的信号。

换句话说,如果QtConcurrent::run(...)完成 beforesetFuture被调用,setFuture仍然会在当前状态上发出信号QFuture。所以,你不需要做任何事情来避免竞争条件。

但是,根据您的代码的其余部分,您可能需要调用QFuture::waitForFinished()以确保您的MyClass,QFuture并且在完成之前QFutureWatcher不会超出范围。 QtConcurrent::run(...)

于 2012-09-21T08:50:28.793 回答
0

我在单元测试中运行这个片段并且QSignalSpy没有从QFutureWatcher. 我通过在检查前显式调用解决了这个问题QCoreApplication::processEvents()

QFutureWatcher<int> watcher;
QSignalSpy spy(&watcher, &QFutureWatcher<int>::finished);

QFuture<int> future = QtConcurrent::run([](){
    qDebug() << "compute";
    return 42;
});
watcher.setFuture(future);
QCOMPARE(watcher.result(), 42);
QCOMPARE(spy.count(), 0);
QCoreApplication::processEvents();
QCOMPARE(spy.count(), 1);

信号可能是从线程发出的,在这种情况下,信号会排队而不是直接执行。

于 2018-07-09T17:33:47.723 回答