当前位置: 首页 > news >正文

QT跨线程阻塞调用方法总结

在 Qt 中实现跨线程阻塞调用(即主线程等待子线程完成任务)通常使用 QMetaObject::invokeMethod() + Qt::BlockingQueuedConnection 或结合 QEventLoop 实现。以下是两种安全实现方式:


方法 1:使用 Qt::BlockingQueuedConnection(推荐)

cpp

// 1. 在工作线程对象中声明槽函数
class Worker : public QObject {Q_OBJECT
public slots:void blockingTask() {QThread::sleep(2);  // 模拟耗时操作result = 42;        // 存储结果}
public:int result = 0;
};// 2. 主线程调用(阻塞等待)
void MainThreadCall() {Worker worker;QThread workerThread;worker.moveToThread(&workerThread);workerThread.start();// 阻塞调用(关键步骤)QMetaObject::invokeMethod(&worker, "blockingTask", Qt::BlockingQueuedConnection);qDebug() << "Result:" << worker.result; // 输出结果:42workerThread.quit();workerThread.wait();
}

关键点

  • Qt::BlockingQueuedConnection 会阻塞调用线程,直到目标槽函数执行完毕

  • 目标对象必须位于不同线程

  • 目标线程必须运行事件循环(QThread::exec()


方法 2:信号槽 + QEventLoop(异步转同步)

cpp

class Worker : public QObject {Q_OBJECT
public slots:void asyncTask() {QThread::sleep(2);emit taskDone(42);  // 发送完成信号}
signals:void taskDone(int);
};// 主线程调用
void MainThreadCall() {QEventLoop loop;Worker worker;QThread workerThread;worker.moveToThread(&workerThread);// 连接完成信号QObject::connect(&worker, &Worker::taskDone, &loop, &QEventLoop::quit);workerThread.start();// 异步触发任务QMetaObject::invokeMethod(&worker, "asyncTask", Qt::QueuedConnection);loop.exec();  // 阻塞等待信号workerThread.quit();workerThread.wait();
}

⚠️ 重要注意事项

  1. 死锁风险

    • 禁止在 GUI 线程阻塞(导致界面冻结)

    • 避免双向等待(A等B,B等A)

    • 确保目标线程事件循环正常运行

  2. 替代方案

    cpp

    // 更现代的异步方案(Qt 5.15+)
    QFuture<void> future = QtConcurrent::run(&worker, &Worker::heavyTask);
    future.waitForFinished(); // 谨慎使用!
  3. 最佳实践

    • 优先使用异步回调(信号槽/QPromise)

    • 耗时操作禁止阻塞 GUI 线程

    • 必须阻塞时设置超时机制:

      cpp

      QTimer::singleShot(5000, &loop, &QEventLoop::quit); // 5秒超时

在 95% 的场景中,应通过信号槽传递结果而非阻塞调用。阻塞操作是同步逻辑的最后手段,使用时必须明确线程依赖关系和退出条件。

http://www.dtcms.com/a/316400.html

相关文章:

  • SpringMVC 6+源码分析(四)DispatcherServlet实例化流程 3--(HandlerAdapter初始化)
  • 【机器学习深度学习】 知识蒸馏
  • 2.4.9-2.5.1监控项目工作-控制质量-确认范围-结束项目或阶段
  • 三极管三种基本放大电路:共射、共集、共基放大电路
  • 后量子时代已至?中国量子加密技术突破与网络安全新基建
  • 无监督学习聚类方法——K-means 聚类及应用
  • CMAQ空气质量模式实践技术及案例分析应用;CMAQ空气质量模式配置、运行
  • Go语言实战案例:使用sync.Mutex实现资源加锁
  • 一次完整的 Docker 启动失败排错之旅:从 `start-limit` 到 `network not found
  • 三坐标测量机全自研扫描测头+标配高端性能,铸就坚实技术根基
  • 如何实现一个简单的基于Spring Boot的用户权限管理系统?
  • layernorm backward CUDA优化分析
  • Spring Boot 集成 ShardingSphere 实现读写分离实践
  • MySQL数据类型介绍
  • langchain入门笔记01
  • 【nvidia-B200】Ubuntu 22.04 中安装指定版本的 NVIDIA 驱动时出现依赖冲突
  • 亚马逊否定投放全攻略:精准过滤无效流量的底层逻辑与实战体系
  • 【教育教学】人才培养方案制定
  • Erlang notes[1]
  • 贝叶斯统计从理论到实践
  • G1垃圾回收堆内存分配问题
  • 8位mcu控制器的架构特征是什么?有哪些应用设计?
  • 单片机充电的时候电池电压会被拉高,如何检测电压?
  • 深入解析数据结构之顺序表
  • DAO治理合约开发指南:原理与Solidity实现
  • RocketMq如何保证消息的顺序性
  • 图像处理中的锚点含义
  • 【unity实战】使用unity程序化随机生成3D迷宫
  • 大学生入门:抽象 及 接口
  • 零基础人工智能学习规划之路