2

背景

在我的 Qt5.3 应用程序中,我处理了几个耗时的过程(统计计算)。为了能够在运行一个或多个计算时使用应用程序,我创建了一个名为ProgressManager的类。此管理器注册从抽象类IRunnable继承并实现纯虚拟方法run的计算对象。

每次启动一个新的耗时操作时,都会在与其进度条相连的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 的第 211 行的函数reportResults中,其中函数是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 }
4

1 回答 1

1

我有一个类似的问题。目前,我正在使用 QFutureInterface 而不使用 QtConcurrent,并且我正在手动报告 QFuture 已准备好。由于某种原因,当从不同线程调用 QFutureInterface 类的函数时,我不时会崩溃,这意味着 QFutureInterface 可能不是可重入的,这会自动导致它不是线程安全的,尽管它的代码中存在互斥锁等. 没有关于它的Qt doc,不管它是一个导出的类。我已经采用wysota 的方法在这里评论说,应该查看 QtConcurrent 关于自定义使用 QFutureInterface 的来源,但如果 QtConcurrent 使用时崩溃,QFutureInterface 的代码可能有问题。我正在使用 Qt 5.3.2。

于 2015-07-02T13:47:40.150 回答