QThread【QT】
thread
·
文章目录
线程
thread.h
#ifndef THREAD_H
#define THREAD_H
#include <QWidget>
#include<QThread>
class Thread : public QThread
{
Q_OBJECT
public:
Thread();
void run() override;
signals:
void notify() ;
};
#endif // THREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"thread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void handle() ;
private:
Ui::Widget *ui;
Thread thread ;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
thread.cpp
#include "thread.h"
Thread::Thread()
{
}
void Thread::run()
{
//在新创建的线程中,qt不允许直接对界面进行修改
//虽然不可以修改界面,但是可以针对时间来进行计时.当每到了一秒钟的时候,通过信号槽,来通知主线程,负责更新的界面内容.
for (int i = 0; i < 10; i++)
{
// sleep 是 QThread 的成员函数,就可以直接调用。
sleep(1);
// 发送一个信号,通知主线程。
emit notify();
}
}
widget.cpp
#include "thread.h"
Thread::Thread()
{
}
void Thread::run()
{
//在新创建的线程中,qt不允许直接对界面进行修改
//虽然不可以修改界面,但是可以针对时间来进行计时.当每到了一秒钟的时候,通过信号槽,来通知主线程,负责更新的界面内容.
for (int i = 0; i < 10; i++)
{
// sleep 是 QThread 的成员函数,就可以直接调用。
sleep(1);
// 发送一个信号,通知主线程。
emit notify();
}
}

start
线程启动
run
exec
quit
QThread 是 Qt 框架封装的线程类,提供了与 Qt 事件循环、信号槽机制深度集成的线程管理能力;而 C++11 std::thread 是标准库的基础线程类,提供更轻量、平台无关的线程操作。以下是 QThread 常用接口的用途及与 std::thread 的对比:
一、QThread 常用接口及用途
| 接口 | 用途说明 | 核心特性 |
|---|---|---|
start(Priority) |
启动线程,触发 run() 函数执行(线程进入运行状态)。Priority 可选(如 Qt::HighPriority),用于设置线程优先级。 |
必须显式调用(线程不会自动启动);优先级设置依赖系统支持。 |
run() |
线程入口函数(默认实现会启动事件循环 exec()),子类可重写以定义线程任务。 |
若重写 run() 且未调用 exec(),线程执行完任务后会直接结束(无事件循环)。 |
exec() |
启动线程的事件循环(仅在 run() 中调用有效),使线程可处理事件(如信号槽、定时器)。 |
事件循环会阻塞等待事件,直到 quit()/exit() 被调用才退出。 |
quit()/exit(int) |
quit() 等价于 exit(0),用于请求事件循环退出(异步操作)。 |
仅对“有事件循环的线程”有效,线程会处理完当前事件后退出。 |
wait(unsigned long timeout) |
阻塞当前线程,等待目标线程结束(超时可选,单位毫秒)。返回 true 表示线程正常结束,false 表示超时。 |
支持超时等待,可多次调用(线程结束后调用立即返回 true)。 |
terminate() |
强制终止线程(危险!不推荐使用)。 | 直接终止线程执行,可能导致资源泄漏、数据不一致(如文件未关闭、锁未释放)。 |
isRunning() |
判断线程是否正在运行(run() 已启动且未结束)。 |
用于查询线程状态。 |
isFinished() |
判断线程是否已结束(run() 执行完毕)。 |
线程结束后返回 true。 |
currentThread() |
静态方法,返回当前执行代码的线程对象指针。 | 类似 std::this_thread::get_id(),用于获取当前线程上下文。 |
moveToThread(QObject*) |
将 QObject 子类对象“移动”到线程中,使该对象的槽函数在目标线程执行(线程安全的信号槽基础)。 |
Qt 独特机制,实现对象与线程的绑定,避免直接操作线程的复杂性。 |
二、与 C++11 std::thread 的核心对比
| 维度 | QThread | std::thread |
|---|---|---|
| 线程启动 | 需显式调用 start() 启动,start() 会触发 run() 执行。 |
构造时传入可调用对象(函数、lambda 等)即自动启动(std::thread t(func))。 |
| 入口函数 | 默认入口是 run()(可重写),默认实现启动事件循环 exec()。 |
入口是构造时传入的可调用对象(无默认实现,需手动定义任务)。 |
| 事件循环 | 内置事件循环(exec()),支持信号槽、定时器、事件处理(Qt 核心优势)。 |
无内置事件循环,需手动实现(如用 std::condition_variable 模拟)。 |
| 线程同步 | wait() 支持超时等待,可多次调用。 |
join() 无超时(必须等待线程结束),且仅能调用一次(否则抛异常);detach() 分离线程(无法再同步)。 |
| 线程安全通信 | 依赖 Qt 信号槽机制(跨线程信号槽自动排队,线程安全)。 | 需手动使用 std::mutex、std::condition_variable 等同步原语。 |
| 对象与线程绑定 | 提供 moveToThread() 机制,方便将对象与线程绑定(槽函数在目标线程执行)。 |
无类似机制,需手动确保对象在线程中安全访问(如通过互斥锁)。 |
| 优先级控制 | start(Priority) 支持线程优先级设置(依赖系统)。 |
需通过 std::thread::native_handle() 结合平台 API(如 pthread_setschedparam)设置,无标准接口。 |
| 强制终止 | 提供 terminate()(不推荐)。 |
无标准强制终止接口,需通过自定义标志位(如 std::atomic<bool>)让线程主动退出。 |
| 适用场景 | Qt 框架内的多线程开发(尤其是需与 UI 交互、依赖事件循环的场景)。 | 纯 C++ 项目、轻量级线程任务、无事件循环需求的场景。 |
三、典型使用场景对比
1. 基础线程任务
-
QThread 方式:
重写run()实现任务,通过start()启动,wait()等待结束。class MyThread : public QThread { protected: void run() override { // 线程任务 for (int i = 0; i < 1000000; ++i) {} } }; // 使用 MyThread t; t.start(); // 启动线程 t.wait(); // 等待结束 -
std::thread方式:
构造时传入任务函数,join()等待结束。void task() { for (int i = 0; i < 1000000; ++i) {} } // 使用 std::thread t(task); t.join(); // 等待结束(必须调用,否则程序可能崩溃)
2. 带事件循环的线程(仅 QThread 支持)
QThread 可通过事件循环处理信号槽、定时器等,std::thread 需手动实现:
// QThread 带事件循环的线程
class Worker : public QObject {
Q_OBJECT
public slots:
void doWork() { /* 处理任务 */ }
};
QThread thread;
Worker worker;
worker.moveToThread(&thread); // 绑定对象到线程
thread.start(); // 启动线程(默认执行 exec() 进入事件循环)
QTimer::singleShot(0, &worker, &Worker::doWork); // 向线程发送任务
四、核心差异总结
- 集成度:QThread 与 Qt 事件循环、信号槽深度绑定,适合 Qt 生态;
std::thread是标准库基础组件,更通用但需手动处理同步。 - 易用性:QThread 提供
moveToThread()、事件循环等高级特性,简化跨线程通信;std::thread更轻量,但需手动管理同步细节。 - 适用场景:Qt 项目优先用 QThread(尤其是需与 UI 交互时);纯 C++ 项目或轻量级任务用
std::thread更合适。
选择时需根据项目是否依赖 Qt 框架、是否需要事件循环机制来决定。
更多推荐


所有评论(0)