如何在不阻止执行的情况下等待线程在Qt中完成?

时间:2015-10-27 00:05:44

标签: c++ multithreading qt

我有一个函数可以创建一堆QThread来加速长时间的计算,但是当我尝试睡眠直到计算结束时,后台线程永远不会因为某些原因而执行。

我无法弄清楚为什么线程在我拨打thread->start()后不会执行。这是我的代码:

multithread.run_multithread(run_function, thread_count);
while(multithread.running)
    QThread::msleep(100);
qDebug() << "done";  // Never reaches this point

多线程函数:

void Multithread::run_multithread(std::function<void
 (int)>run_function_in, int thread_count) {
    running = true;
    // Create workers and threads
    int thread_idx;
    for(thread_idx=0; thread_idx<thread_count; thread_idx++) {
        ThreadWorker *worker = new ThreadWorker(this, run_function_in);
        QThread *thread = new QThread();
        // Set workers and threads to delete when done
        worker->moveToThread(thread);
        connect(worker, &ThreadWorker::finished, this, &Multithread::check_progress);
        connect(thread, &QThread::started, worker, &ThreadWorker::run);
        connect(worker, &ThreadWorker::finished, thread, &QThread::quit);
        connect(worker, &ThreadWorker::finished, worker, &ThreadWorker::deleteLater);
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);
        // Start thread
        thread->start();
    }
}
当所有线程完成部分计算时,<runningfalse中设置为Multithread::check_progress。当我删除QThread::msleep(100)时,计算将正常执行,但我需要一些方法来阻止它完成。

2 个答案:

答案 0 :(得分:1)

我建议使用Qt Concurrent功能,而不是使用QThread,它提供了比线程原语更高级别的抽象。您可以使用QFutureSynchronizer等待多个并发期货完成。该对象将等待所有附加的期货完成,然后才能销毁它。

如何启动多个线程然后等待它们全部完成的示例是:

#include <QtConcurrent>

void run_multithread(...) {
  // Set up a new synchronizer.
  QFutureSynchronizer<void> synchronizer;

  // Run n tasks in parallel.
  for (int thread_idx = 0; thread_idx < thread_count; ++thread_idx) {
    synchronizer.addFuture(QtConcurrent::run(run_function_in));
  }

  // The synchroniser will wait for all threads to finish before returning.
}

答案 1 :(得分:0)

可能是因为优化,因为multithread.running在循环内没有改变。但是,这里主要的可重现原因是Multithread::check_progress信号永远不会调用插槽ThreadWorker::finished,因为Multithread的实例属于您当前的线程,但事件循环被阻塞。 / p>

当所有线程都完成时,您可以从Multithread对象发出信号,而不是这样的睡眠。然后可以从连接到该信号的时隙继续计算。