Qt 通过继承QObject实现多线程
Qt实现多线程
最简单的多线程示例包含:
- MainWindow:主线程,负责GUI
- Worker:干活的对象
- Worker::resultReady:子线程发出的信号
- QThread:线程控制器
名称 | 类型 | 职责 | 说明 |
---|---|---|---|
MainWindow |
QWidget 子类 |
图形界面,主线程运行 | 控制整个应用,接收子线程数据 |
QThread |
Qt线程类 | 提供线程上下文(事件循环) | 不是干活的,是“搬家工人 + 开个房间” |
Worker |
QObject 子类 |
真正干活的对象 | 会被搬进 QThread 管理的线程空间 |
QObject::moveToThread(QThread*) |
方法 | 把对象“搬”进线程空间 | 只有 QObject 的子类可以这么搬 |
QTimer |
定时器 | 定期调用 Worker::timeout() |
运行在线程内,不阻塞主线程 |
- 主线程 = 总公司,负责 UI 显示
- QThread = 新开了一个工厂的“独立办公室”
- Worker = 工人在新办公室干活
- moveToThread = 把工人搬去那边
- 信号/槽 = 发邮件通知主公司,数据干活好了
1 |
|
Qt多线程中的重要概念是”事件循环“。每个线程可以拥有一个事件循环,通过moveToThread()
把 Worker
放进去,它就“生活在”那个线程中了。
线程中的代码不能够直接访问GUI,会引起线程安全问题。只能通过信号将结果传回主线程。
项目示例
mainwindow.cpp
1 |
|
整个线程的创建步骤为:
- 线程对象与Worker对象创建
1 |
|
- Worker对象:负责实际耗时操作的业务逻辑(需继承QObject)。
- moveToThread():将Worker的事件循环绑定到workerThread线程。此后Worker的槽函数会在新线程中执行。
- 线程生命周期管理
1 |
|
线程结束时自动清理资源:
- 当线程finished()时,触发worker->deleteLater(),确保Worker对象在事件循环中安全删除。
- 线程自身也通过deleteLater()自动销毁,避免内存泄漏。
- 信号-槽通信机制
主线程通知Worker开始工作:
1 |
|
- 跨线程通信:通过发射startWork信号,触发Worker的doWork1槽函数。
- 队列连接(Queued Connection):由于Worker位于不同线程,Qt自动使用队列连接,确保槽函数在目标线程执行。
Worker反馈结果到主线程:
1 |
|
- 线程安全更新UI:Worker通过信号resultReady传递结果,主线程的handlerResults接收并处理(如更新界面),符合“UI操作必须在主线程”原则。
- 线程启动与停止
启动线程:
1 |
|
- start():启动线程的事件循环,等待处理任务。
- 发射信号:通知Worker在新线程中执行doWork1。
停止线程:
1 |
|
- stopWork():Worker内部应检查标志(如QAtomicInt)安全退出循环。
- quit() + wait():优雅终止线程,quit()退出事件循环,wait()阻塞等待线程结束。
- 线程执行流程
- 用户点击按钮1 → workerThread.start()启动线程。
- 主线程发射startWork信号 → Worker的doWork1在新线程执行。
- Worker处理完成 → 发射resultReady信号 → 主线程更新UI。
- 用户点击按钮2或窗口关闭 → 调用stopWork()终止任务,线程退出并清理资源。
Qt 通过继承QObject实现多线程
http://akichen891.github.io/2025/04/23/Qt多线程/