В моем приложении Qt5.3 я имею дело с несколькими трудоемкими процессами (статистические вычисления). Чтобы иметь возможность работать с приложением во время выполнения одного или нескольких вычислений, я создал класс под названием ProgressManager. Этот менеджер регистрирует вычислительные объекты, которые наследуются от абстрактного класса IRunnable и реализовать чисто виртуальный метод бежать.
Каждый раз, когда начинается новая трудоемкая операция, она регистрируется в ProgressManager подключился к его индикатору и запустил следующую функцию:
void ProgressManager::runProgress(const QVariant &id, const QVariant ¶m) {
// 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 }
У меня похожая проблема. В настоящее время я использую QFutureInterface без QtConcurrent и вручную сообщаю, что QFuture готов. По какой-то причине время от времени я получаю сбои, когда функции класса QFutureInterface вызываются из разных потоков, что означает, что QFutureInterface, вероятно, не реентерабелен, что автоматически приводит к тому, что он не является потокобезопасным, несмотря на наличие мьютексов в его коде и т. Д. В нем нет Qt doc, независимо от того, является ли это экспортируемым классом. Я взял Подход Wysota прокомментировал здесь что нужно посмотреть на источники QtConcurrent о пользовательском использовании QFutureInterface, но, вероятно, что-то не так с кодом QFutureInterface, если происходит сбой при использовании даже QtConcurrent. Я использую Qt 5.3.2.