我如何在Qt中等待线程完成而不阻塞其执行

How do I wait for a thread to finish in Qt without blocking its execution?

本文关键字:执行 线程 Qt 等待      更新时间:2023-10-16

我有一个函数,它创建了一堆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();
    }
}
Multithread::check_progress中,当所有线程完成各自的计算后,

running被设置为false。当我删除QThread::msleep(100)计算将正常执行,但我需要一些方法阻塞,直到它完成。

与其使用QThread,我建议使用Qt Concurrent功能,它提供了线程原语之上更高层次的抽象。你可以使用QFutureSynchronizer来等待几个并发的期货完成。此对象将等待所有附加的future完成后才允许自己被销毁。

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

#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.
}

这可能是因为优化,因为multithread.running没有在循环内更改。然而,这里主要的可重复的原因是插槽Multithread::check_progress从未被ThreadWorker::finished信号调用,因为Multithread的实例属于当前线程,但是事件循环被阻塞了。

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