如何在Qt中创建并行线程?附Worker线程管理类实现代码
嘿,我来帮你捋捋Qt里创建并行线程的正确姿势,顺便看看你写的Worker类怎么优化~
在Qt中创建并行线程的正确方法
Qt里创建并行线程主要有两种常用模式,我一个个给你拆解:
1. Worker对象+QThread模式(官方推荐)
这是Qt官方最推荐的方式——把业务逻辑封装在继承自QObject的Worker类里,再把这个对象移到独立的QThread中运行,和你现在的思路方向一致,但代码细节还有优化空间。
先看标准的Worker类结构
#include <QObject> #include <QThread> #include <QDebug> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = nullptr) : QObject(parent), m_isRunning(false) {} // 注意:耗时操作绝对不能放在构造函数里,要放到槽函数中执行 public slots: void startWork() { m_isRunning = true; // 这里写你的核心业务逻辑,比如调用QProcess、处理文件等 while(m_isRunning) { qDebug() << "Worker running in thread ID:" << QThread::currentThreadId(); // 加个小延时避免CPU被占满,根据你的业务调整 QThread::msleep(100); } emit workFinished(); } void stopWork() { // 优雅停止线程,不要用强制终止 m_isRunning = false; } signals: void workFinished(); void errorHappened(const QString &errorMsg); private: // 用QAtomicBool保证多线程下的线程安全,比普通bool更可靠 QAtomicBool m_isRunning; };
主线程中如何使用这个Worker
// 比如在MainWindow或者其他主线程对象中初始化 Worker *myWorker = new Worker(); QThread *workerThread = new QThread(); // 连接信号槽,管理线程生命周期 connect(workerThread, &QThread::started, myWorker, &Worker::startWork); connect(myWorker, &Worker::workFinished, workerThread, &QThread::quit); // 线程结束后自动释放资源,避免内存泄漏 connect(myWorker, &Worker::workFinished, myWorker, &Worker::deleteLater); connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater); // 把Worker对象移到子线程中 myWorker->moveToThread(workerThread); // 启动线程 workerThread->start(); // 当需要停止线程时,调用Worker的stopWork槽即可 // myWorker->stopWork();
针对你写的Worker_Bis类的修正建议
你的代码思路是对的,但有几个细节要调整:
- 不要在Worker的构造函数里直接
new QThread()并moveToThread,应该在主线程中创建QThread,再把Worker移过去,这样线程的生命周期管理更清晰。 - 用
QAtomicBool代替普通的flag_running和flag_stopping,避免多线程下的竞态问题。 - 尽量用Qt5的新信号槽语法(
&类名::信号/槽),比旧的SIGNAL/SLOT宏更安全,编译期就能检查错误。 - 记得补全未写完的信号槽连接,比如线程结束后要自动释放线程和Worker对象,避免内存泄漏。
2. 继承QThread重写run()方法(不推荐)
这种方式是直接继承QThread,把业务逻辑写在重写的run()方法里,但Qt官方不推荐这么做——因为QThread本质是线程的管理类,不是线程的载体,容易出现对象生命周期混乱的问题。不过还是给你举个例子参考:
#include <QThread> #include <QDebug> class MyThread : public QThread { Q_OBJECT protected: void run() override { qDebug() << "Thread running with ID:" << currentThreadId(); // 耗时操作逻辑 while(!isInterruptionRequested()) { // 你的业务代码 msleep(100); } } }; // 使用方式 MyThread *thread = new MyThread(); connect(thread, &QThread::finished, thread, &QThread::deleteLater); thread->start(); // 停止线程时用优雅的方式 // thread->requestInterruption(); // thread->wait();
关键注意事项
- 线程安全:绝对不要在子线程中操作UI控件!Qt的UI类只能在主线程(GUI线程)中访问,如果需要更新UI,要通过信号槽把数据传到主线程处理。
- 资源释放:一定要用
deleteLater()确保线程和Worker对象在合适的时机被销毁,避免内存泄漏。 - 避免强制终止:永远不要用
terminate()方法终止线程,这会导致线程资源无法正常释放,要用标志位或者requestInterruption()优雅停止。
内容的提问来源于stack exchange,提问作者Bismarck Gomes




