Qt 多线程与信号槽机制

📅 发布时间:2026/7/16 18:18:41 👁️ 浏览次数:
Qt 多线程与信号槽机制
在 Qt 中信号与槽不仅仅用于同线程内的对象通信更重要的是它支持跨线程通信这是其区别于许多 GUI 框架的强大特性。一、为什么要用信号与槽来做线程通信直接在线程之间访问对象或变量容易出现竞态条件和线程安全问题。而信号与槽提供了一种线程安全的通信方式不需要手动加锁只要正确连接保证槽函数在接收者对象所属线程中执行支持同步或异步方式DirectvsQueued二、Qt 线程模型简介QThread是 Qt 提供的线程类。Qt 中的QObject 默认属于创建它的线程通常是主线程。你不能直接在QThread中放业务逻辑应将逻辑封装为对象如 Worker 类并将该对象“移动”到目标线程中。三、线程中的信号与槽连接类型在不同线程的对象之间连接信号与槽默认使用的是Qt::QueuedConnection这意味着发射信号的线程将信号事件放入接收者线程的事件队列中槽函数在接收者的线程中执行必须运行事件循环四、完整示例主线程控制 工作线程执行 信号传回主线程结构说明Worker类负责在子线程中执行耗时任务MainWindow或main()负责创建线程、连接信号与槽、控制流程 Worker.h#ifndef WORKER_H #define WORKER_H #include QObject #include QDebug #include QThread class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent nullptr) {} public slots: void doWork() { qDebug() Worker thread ID: QThread::currentThreadId(); // 模拟耗时操作 for (int i 0; i 5; i) { QThread::sleep(1); emit progress(i * 20); } emit finished(); } signals: void progress(int percent); void finished(); }; #endif // WORKER_H main.cpp#include QCoreApplication #include QThread #include Worker.h int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() Main thread ID: QThread::currentThreadId(); QThread* workerThread new QThread; Worker* worker new Worker(); // 将 Worker 移动到线程 worker-moveToThread(workerThread); // 启动线程时调用 doWork QObject::connect(workerThread, QThread::started, worker, Worker::doWork); // 工作完成后退出线程 QObject::connect(worker, Worker::finished, workerThread, QThread::quit); // 删除线程和对象安全释放资源 QObject::connect(worker, Worker::finished, worker, QObject::deleteLater); QObject::connect(workerThread, QThread::finished, workerThread, QObject::deleteLater); // 监听进度主线程槽函数响应 QObject::connect(worker, Worker::progress, [](int val){ qDebug() Progress: val % — Thread: QThread::currentThreadId(); }); // 启动线程 workerThread-start(); return a.exec(); }五、输出示例Main thread ID: 0x78e8 Worker thread ID: 0x78f8 Progress: 0 % — Thread: 0x78f8 Progress: 20 % — Thread: 0x78f8 Progress: 40 % — Thread: 0x78f8 Progress: 60 % — Thread: 0x78f8 Progress: 80 % — Thread: 0x78f8 ...注意槽函数在主线程中执行说明QueuedConnection生效。六、重点讲解为什么这样做是正确方式步骤原因使用moveToThread()确保对象所属线程为子线程不在 QThread 子类中写业务推荐将业务与线程分离便于复用使用信号启动与回传保证线程安全、可控性强自动释放资源使用deleteLater()确保在所属线程安全释放七、问题和要点问题要点如何实现 Qt 跨线程通信使用信号与槽类型为Qt::QueuedConnectionmoveToThread有什么作用改变对象所属线程确保槽函数在目标线程中运行为什么不能直接继承QThread干活会让逻辑和线程耦合且 run() 中无事件循环怎样安全退出线程发出finished信号连接到QThread::quit()并 deleteLater()✅ 总结关键点说明跨线程通信使用信号与槽QueuedConnection线程安全槽函数在接收者线程中执行不直接调用正确方式使用 Worker moveToThread() 构建线程模型生命周期管理deleteLater finished 信号自动清理