QtConcurrent аварийно завершает работу на reportResultsReady

Фон

В моем приложении Qt5.3 я имею дело с несколькими трудоемкими процессами (статистические вычисления). Чтобы иметь возможность работать с приложением во время выполнения одного или нескольких вычислений, я создал класс под названием ProgressManager. Этот менеджер регистрирует вычислительные объекты, которые наследуются от абстрактного класса IRunnable и реализовать чисто виртуальный метод бежать.

Каждый раз, когда начинается новая трудоемкая операция, она регистрируется в ProgressManager подключился к его индикатору и запустил следующую функцию:

void ProgressManager::runProgress(const QVariant &id, const QVariant &param) {

// If progress is not present, exit
if (!progs.contains(id)) {
return;
}

// If progress is not runnable, exit
IRunnable* runnable = dynamic_cast<IRunnable*>(progs.value(id));
if (!runnable) {
return;
}

// Create future watcher
QFutureWatcher<QVariant>* watcher = new QFutureWatcher<QVariant>();
connect(watcher, SIGNAL(finished()), this, SLOT(handleFinished()));

// Register running progress
running.insert(watcher, id);

// Paralelize runnable progress
QFuture<QVariant> future = QtConcurrent::run(runnable, &IRunnable::run, param);
watcher->setFuture(future);
}

После завершения параллельного процесса должна быть вызвана следующая функция:

void ProgressManager::handleFinished() {

// Retrieves sender watcher
QObject* s = this->sender();
QFutureWatcher<QVariant>* w = dynamic_cast<QFutureWatcher<QVariant>*>(s);

// Retrieve ID of running progress and delete watcher
QVariant id = running.value(w);
running.remove(w);
delete w;

// Emit progress has finished
emit finished(id);
}

проблема

Все идет гладко, пока не будет достигнут конец парализованного процесса. Затем приложение происходит сбой каждый раз с ошибкой сегментации, прежде чем вызывать сигнал завершения и обрабатывать слоты.

О сбое сообщается в файле qfutureinterface.h в функции reportResults в строке 211, где функция reportResultsReady называется:

194 template <typename T>
195 inline void QFutureInterface<T>::reportResult(const T *result, int index)
196 {
197     QMutexLocker locker(mutex());
198     if (this->queryState(Canceled) || this->queryState(Finished)) {
199         return;
200     }
201
202     QtPrivate::ResultStore<T> &store = resultStore();
203
204
205     if (store.filterMode()) {
206         const int resultCountBefore = store.count();
207         store.addResult(index, result);
208         this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
209     } else {
210         const int insertIndex = store.addResult(index, result);
211         this->reportResultsReady(insertIndex, insertIndex + 1);
212     }
213 }

2

Решение

У меня похожая проблема. В настоящее время я использую QFutureInterface без QtConcurrent и вручную сообщаю, что QFuture готов. По какой-то причине время от времени я получаю сбои, когда функции класса QFutureInterface вызываются из разных потоков, что означает, что QFutureInterface, вероятно, не реентерабелен, что автоматически приводит к тому, что он не является потокобезопасным, несмотря на наличие мьютексов в его коде и т. Д. В нем нет Qt doc, независимо от того, является ли это экспортируемым классом. Я взял Подход Wysota прокомментировал здесь что нужно посмотреть на источники QtConcurrent о пользовательском использовании QFutureInterface, но, вероятно, что-то не так с кодом QFutureInterface, если происходит сбой при использовании даже QtConcurrent. Я использую Qt 5.3.2.

1

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


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