Как я могу использовать QFutureWatcher с QtConcurrent :: run () без условия гонки

Если я правильно понимаю следующий код из документации 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() сигнал никогда не сработает. Правильно ли мое предположение? Как мне обойти эту ошибку?

9

Решение

От http://doc.qt.io/qt-4.8/qfuturewatcher.html#setFuture

Один из сигналов может быть излучен для текущего состояния
будущее. Например, если будущее уже остановлено, готово
сигнал будет излучаться.

Другими словами, если QtConcurrent::run(...) завершается раньше setFuture называется, setFuture будет по-прежнему излучать сигнал о текущем состоянии QFuture, Таким образом, вам не нужно ничего делать, чтобы избежать состояния гонки.

Однако, в зависимости от остальной части вашего кода, вам может потребоваться позвонить QFuture::waitForFinished() для того, чтобы ваш MyClass, QFuture а также QFutureWatcher не выходи за рамки до QtConcurrent::run(...) завершается.

11

Другие решения

Я запускал этот разрез в модульном тесте и 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);

Сигнал, вероятно, испускается из потока, и в этой ситуации сигнал ставится в очередь вместо непосредственного выполнения.

0

По вопросам рекламы [email protected]