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

QT GUI中嵌套QThread的子线程信号无法被父线程接收问题咨询

问题根因分析

该问题和线程嵌套架构无关,核心是两个代码逻辑错误,完全对应你测试到的现象:

  1. 接收信号的ServerStart对象提前被销毁
    你在ServerStart::run()方法末尾直接调用了this->deleteLater(),如果没有开启注释掉的死循环functionthathasinfiniteloop(),run()方法启动子线程后会立刻执行完毕,ServerStart实例直接被回收。
    你直接调用listenerthread->run()时是同步执行,信号发射时ServerStart::run()还没执行完,deleteLater还没触发对象销毁,所以槽函数能正常触发;当你把listenerthread移动到新线程运行时,跨线程信号默认走队列异步投递,信号投递到接收方的时候ServerStart已经被销毁,自然收不到信号。
  2. 若ServerStart实例本身也运行在自定义子线程中,需要确保该线程的事件循环没有被阻塞,否则队列投递的信号无法被正常派发执行。
修复方案
// 修改serverstartThread.cpp中的run方法
void ServerStart::run()
{
    qInfo() << "\nthread is running\n";

    //监听新连接
    listenerthread = new listenerThread();
    thread = new QThread(this);
    listenerthread->moveToThread(thread);
    // 绑定线程结束后自动销毁关联对象,避免内存泄漏
    connect(thread, &QThread::finished, listenerthread, &QObject::deleteLater);
    connect(thread, &QThread::finished, thread, &QObject::deleteLater);
    QObject::connect(thread, &QThread::started, listenerthread, &listenerThread::run);
    // 跨线程连接显式指定队列连接更稳妥
    QObject::connect(listenerthread, &listenerThread::newClientConnectedSig, this, &ServerStart::newClientConnectedSig2, Qt::QueuedConnection);
    thread->start();

    // 需要长期接收信号就删除这行,不要提前销毁自身
    // this->deleteLater();
}
补充规范
  • QThread本身是线程控制器,不是线程实体,不要继承QThread重写run方法,moveToThread是Qt官方推荐的多线程实现方案
  • 跨线程的队列信号槽依赖接收方所在线程的事件循环,不要在接收方所在线程执行长期阻塞的逻辑,避免事件派发中断

内容的提问来源于stack exchange,提问作者anasouardini5

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:54:03