1. 同线程信号与槽的实现原理
- 默认连接方式:如果信号和槽在同一线程,默认使用 直接连接(
DirectConnection)。 - 调用机制:信号发出时,Qt 内部实际上就是调用一个函数指针列表,直接执行槽函数。
- 编译时 moc 工具会为每个类生成
meta-object(QMetaObject),里面记录了信号与槽的索引、函数指针。 QObject::connect时,Qt 把信号和槽的映射关系存到内部的QObjectPrivate::Connection链表里。- 触发信号时,会遍历连接表,直接调用对应槽函数
- 编译时 moc 工具会为每个类生成
- 关键点:同线程的信号槽其实就是函数回调,不会涉及事件循环,也没有上下文切换。
2. 跨线程信号与槽的实现原理
- 默认连接方式:如果信号和槽在不同线程,默认使用 队列连接(
QueuedConnection)。 - 调用机制:
- 发射信号时,Qt 并不会立刻调用槽函数,而是把调用请求封装成一个
QMetaCallEvent(继承自QEvent)。 - 这个事件被投递到目标线程对象所属的
QObject的事件队列里。- 内部用
QCoreApplication::postEvent()把事件压入目标线程的事件循环。
- 内部用
- 目标线程的
QEventLoop在处理事件时,解析QMetaCallEvent,找到对应槽函数,最后在目标线程上下文中调用。
- 发射信号时,Qt 并不会立刻调用槽函数,而是把调用请求封装成一个
- 关键点:跨线程槽函数执行的时机取决于目标线程事件循环,如果目标线程没有运行
exec()(没有事件循环),则槽函数不会执行。
3. 连接方式
Qt 提供几种连接类型:
Qt::AutoConnection(默认):同线程用 直接连接,不同线程用 队列连接。Qt::DirectConnection:强制直接调用。Qt::QueuedConnection:强制事件队列方式。Qt::BlockingQueuedConnection:类似QueuedConnection,但发射信号的线程会阻塞,直到槽函数执行完。Qt::UniqueConnection:避免重复连接。
4. 总结
- 同线程:信号槽就是函数指针回调,直接调用。
- 跨线程:信号槽被封装成
QMetaCallEvent通过postEvent投递到目标线程事件循环,在线程上下文中异步执行。
9789

被折叠的 条评论
为什么被折叠?



