You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt使用QThread实现多线程运行,为何代码仍执行在主线程?

问题本质

你对Qt线程模型的使用存在两个核心错误:

  1. 普通C++成员函数调用不受moveToThread影响:func虽然被移动到了子线程,但你直接调用func->compute()属于普通同步函数调用,永远执行在调用者所在的线程(也就是你的主线程)。
  2. 要让函数执行在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:15:03