关于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
相关产品推荐
相关产品推荐

