You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于QThreadPool与QRunnable使用的三个技术问题

Qt QThreadPool相关问题解答

我正在阅读法语书籍《Maîtrisez Qt 5: guide de développement d'applications professionnelles》学习Qt,书中有一段解释QThreadPool的示例代码:

#include "MaTache.h"
#include <QCoreApplication>
#include <QThreadPool>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QThreadPool::globalInstance()->setMaxThreadCount(3);

    for(int i = 0 ; i < 10 ; i++) {
        MaTache *t = new MaTache; // MaTache inherits from QRunnable
        QThreadPool::globalInstance()->start(t);
    }
    
    QThreadPool::globalInstance()->waitForDone();

    return 0;
}

结合Qt官方文档的两处说明:

当autoDelete启用时,多次使用同一个QRunnable调用QThreadPool::start()会产生竞态条件,不推荐此操作。
QThreadPool::waitForDone(QDeadlineTimer deadline = QDeadlineTimer::Forever):等待直到截止时间到期,所有线程退出并从线程池中移除,若所有线程都被移除则返回true,否则返回false。

针对以上内容,解答三个问题:


问题1:建议中提到的“同一个QRunnable”指的是同一个类还是同一个类实例?示例中使用同一个类但不同实例,是否存在竞态条件?

  • 这里的“同一个QRunnable”指的是同一个类实例,而非同一个类。
  • 示例代码里每次循环都new一个新的MaTache实例,每个实例都是独立的,不存在多次调用start()操作同一个实例的情况,所以不会触发文档里提到的竞态条件,完全符合安全规范。

问题2:若在调用start前添加t->setAutoDelete(false);(默认值为true),该如何手动删除QRunnable?

当autoDelete设为false时,线程池不会自动销毁QRunnable实例,需要手动管理内存:

  • 方式一:在QRunnable的run()方法末尾调用delete this;,让实例在任务执行完毕后自行销毁。
  • 方式二:调用waitForDone()确保所有任务执行完成后,遍历所有保存的QRunnable实例指针逐个delete(前提是你要提前保留这些实例的引用)。
  • 注意:绝对不能在任务执行过程中随意删除实例,必须等任务完全结束后再操作,否则会引发内存访问错误。

问题3:前一问题涉及QRunnable的删除,而QThreadPool::waitForDone用于移除线程,是否可根据QRunnable的删除模式随意使用它?

waitForDone()的作用是等待线程池内所有任务执行完毕、线程退出并从池中移除,它和QRunnable的autoDelete模式无关,不管autoDelete是true还是false,都可以正常调用:

  • 当autoDelete=true:waitForDone()等待所有任务完成后,线程池会自动销毁所有QRunnable实例,之后线程退出并移除。
  • 当autoDelete=false:waitForDone()同样等待所有任务完成、线程退出移除,但QRunnable实例需要按照问题2的方式手动销毁。
  • 需要注意:调用waitForDone()后,尽量不要再向线程池提交新任务,否则可能导致未预期的阻塞或任务执行异常。

内容的提问来源于stack exchange,提问作者kingsjester

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:02:45