信号槽
多线程下信号槽在什么线程中执行
Connect原型
bool QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *slot, Qt::ConnectionType type = Qt::AutoConnection);
- 直接连接(Qt::DirectConnection):信号槽在信号发出者所在的线程中执行
- 队列连接(Qt::QueuedConnection):信号在信号发出者所在线程中执行,槽函数在信号接收者所在线程中执行
- 自动连接(Qt::AutoConnection):多线程时队列连接函数,单线程时为直接连接。
不难看出,connect的第五个参数用于确定连接方式,因此可以控制信号槽执行时所在的线程。
Qt信号与槽如何同步异步
Qt默认单线程的信号与槽的连接为同步的,也就是直连方式,只要信号触发,一定会优先执行槽函数,槽函数执行结束后则返回到信号调用的位置。
默认多线程的信号与槽的连接为异步的,也就是队列方式,信号触发后不会等待槽函数结束,会直接往后执行,而槽函数在事件循环中排队,等待签名的事件执行完再开始执行。
多线程中若想同步需要将连接类型配置为Qt::BlockingQueuedConnection(阻塞排队方式),信号发送完成后会等待槽函数执行完才会往后执行,而槽函数在事件循环中排队,等待签名的事件执行完再开始执行。
优缺点
优点 | 原因/应用 |
松耦合 | 信号发送者不需要知道哪个槽会接收信号,这降低了组件之间的依赖性 |
跨线程通信 多线程安全 | Qt支持信号槽的跨线程通信,可用于跨线程通讯 |
灵活性 | 一个信号可以连接到多个槽,多个信号也可以连接到同一个槽,甚至可以连接信号到另一个信号 |
缺点 | 原因/应用 |
性能开销 | 信号槽机制在运行时有一定的性能开销,尤其是在信号连接非常多的情况下。(需要遍历槽) 可能比直接调用慢一个数量级。 |
调试复杂 | 信号槽机制隐藏了调用关系,当程序出现问题时,可能难以追踪信号是如何触发槽函数的。 |
内存管理和资源释放
对象树:当一个对象被添加为另一个对象的子对象时,Qt会自动管理子对象的内存,确保在父对象被销毁时,子对象也会被正确地销毁,从而避免内存泄漏。
智能指针:Qt提供了 QSharedPointer、QWeakPointer和QScopedPointer来管理对象的生命周期。只要用于防止内存泄漏。
优化
避免频繁分配和释放资源:考虑使用池化技术。
减少信号槽连接:考虑牺牲耦合度或合并信号。
减少对象的复制:考虑转移方法。
清理无用的对象和资源:可以使用deleteLater()函数来延迟删除对象,或者使用Qt的对象树来自动管理对象的生命周期。