信号槽常见坑与最佳实践
常见坑位
- 重负载槽配 Direct/同线程 Auto:
- 卡住发射线程(可能是 UI);改为 Queued 或下放到 Worker。
- 跨线程 Direct:
- 槽在发射线程执行,可能越线程访问接收者;跨线程应用 Queued/BlockingQueued。
- 子线程无事件循环:
- Queued 的槽不执行;子线程需进入
QThread::exec()
。
- 自定义参数未注册:
- 队列连接跨线程传参需
Q_DECLARE_METATYPE
+ qRegisterMetaType<T>()
。
- 误用 BlockingQueued:
- 同线程死锁;不同线程也可能因锁顺序错误死锁;仅在确需同步等待时使用。
- 重复连接:
- 导致槽多次触发;用
Qt::UniqueConnection
或在连接前断开旧连接。
- lambda 捕获悬垂:
- 捕获裸指针生命周期不受控;使用接收者作为上下文对象(自动断连)或
QPointer
。
- 在子线程触碰 UI 对象:
- 未定义行为;所有 UI 更新切回 GUI 线程。
最佳实践
- 连接类型选型:默认 Auto;跨线程显式 Queued;等待结果用 BlockingQueued(谨慎)。
- 线程架构:Worker 对象移到子线程;结果通过信号回 UI。
- 轻重分离:耗时任务放后台;UI 线程仅做轻量更新;需要时切片(
QTimer::singleShot(0, ...)
)。
- 参数传递:跨线程避免大对象拷贝,优先轻量数据或共享指针。
- 连接管理:保存
QMetaObject::Connection
以便断开;或用上下文对象自动断连。
- 语法选择:优先“新语法”(函数指针/成员指针)获得编译期检查;重载信号用
QOverload<>
辅助。
参考与关联