QT GUI中嵌套QThread的子线程信号无法被父线程接收问题咨询
问题根因分析
该问题和线程嵌套架构无关,核心是两个代码逻辑错误,完全对应你测试到的现象:
- 接收信号的ServerStart对象提前被销毁
你在ServerStart::run()方法末尾直接调用了this->deleteLater(),如果没有开启注释掉的死循环functionthathasinfiniteloop(),run()方法启动子线程后会立刻执行完毕,ServerStart实例直接被回收。
你直接调用listenerthread->run()时是同步执行,信号发射时ServerStart::run()还没执行完,deleteLater还没触发对象销毁,所以槽函数能正常触发;当你把listenerthread移动到新线程运行时,跨线程信号默认走队列异步投递,信号投递到接收方的时候ServerStart已经被销毁,自然收不到信号。 - 若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
相关产品推荐
相关产品推荐

