Qt使用QThread实现多线程运行,为何代码仍执行在主线程?
问题本质
你对Qt线程模型的使用存在两个核心错误:
- 普通C++成员函数调用不受
moveToThread影响:func虽然被移动到了子线程,但你直接调用func->compute()属于普通同步函数调用,永远执行在调用者所在的线程(也就是你的主线程)。 - 要让函数执行在QObject所属的线程,必须通过Qt的事件循环投递调用,要么用跨线程信号槽,要么用
QMetaObject::invokeMethod指定队列连接,且被调用的函数必须是槽函数或者被Q_INVOKABLE修饰。
修复步骤
1. 将Func的compute方法声明为槽函数
修改func.h中compute的声明:
class Func : public QObject { Q_OBJECT public: explicit Func() { qDebug() << Q_FUNC_INFO << QThread::currentThreadId(); } // 新增public slots修饰 public slots: void compute() { qDebug() << Q_FUNC_INFO << QThread::currentThreadId(); } };
2. 修改Core的compute逻辑,通过事件循环投递调用
有两种常用实现方式,二选一即可:
方案A:用信号槽连接实现
修改core.h如下:
class Core : public QObject { Q_OBJECT QThread thread; Func* func = nullptr; public: explicit Core(QObject *parent = nullptr) { func = new Func(); func->moveToThread(&thread); connect(&thread, &QThread::finished, func, &QObject::deleteLater); // 新增信号槽连接,触发时自动投递到func所属线程执行 connect(this, &Core::triggerCompute, func, &Func::compute); thread.start(); } ~Core() { thread.quit(); thread.wait(); } public: void compute(){ // 发信号即可,Qt会自动处理跨线程投递 emit triggerCompute(); } signals: // 新增触发信号 void triggerCompute(); };
方案B:用invokeMethod直接投递调用
不需要新增信号,直接修改Core的compute方法即可:
public slots: void compute(){ // 显式将compute调用投递到func所属线程的事件队列 QMetaObject::invokeMethod(func, "compute", Qt::QueuedConnection); }
额外说明
你输出中Func::Func()执行在主线程是正常现象:因为你是在Core的构造函数(主线程执行)中创建的Func对象,对象构造属于普通函数调用,不受后续moveToThread影响。如果需要Func的构造也执行在子线程,需要调整对象创建逻辑,将创建操作也投递到子线程执行。
修改完成后运行,Func::compute()的线程ID就会和主线程不同,符合多线程执行预期。
内容的提问来源于stack exchange,提问作者KcFnMi
相关产品推荐
相关产品推荐

