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

Qt中连接到同一signal的多个slots的执行顺序问题

  • in the order they have been connected

起源

前些天忘记在哪儿讨论过这个问题,今天在csdn又看到有网友问这个问题,而其他网友却无一例外的给出了“无序”这个答案。

Manual

Qt的问题,当manual中有明确文字说明时,我们应该以Qt的manual为准:

http://doc.qt.nokia.com/4.8/signalsandslots.html

If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.

或者http://doc.qt.nokia.com/4.8/qobject.html

If a signal is connected to several slots, the slots are activated in the same order as the order the connection was made, when the signal is emitted.

恩,说的很明确,各个槽按照被connect的顺序被执行【注意,在队列模式时,是指相应的事件被post,仍不保证槽被按照该顺序执行】。

可是,为什么很多人认为是无序呢?(除了前面提及的,还有什么其他因素么?)

翻翻Qt4.5以及该版本之前的manual,可以看到

http://doc.qt.nokia.com/4.5/signalsandslots.html

If several slots are connected to one signal, the slots will be executed one after the other, in an arbitrary order, when the signal is emitted.

以及http://doc.qt.nokia.com/4.5/qobject.html

If a signal is connected to several slots, the slots are activated in an arbitrary order when the signal is emitted.

网络上以及书籍中的大部分资料都是Qt4.6之前的,故尔 ...

源码

恩,尝试看过元对象系统这部分源码的网友对这部分不会觉得陌生。如果没看过,可以瞅瞅这个Qt Meta Object system 学习(三)

  • QObject::connect() 最终将 信号和槽的索引值放置到一个Connection列表中

QObjectPrivate::Connection *c = new QObjectPrivate::Connection; 
    c->sender = s; 
    c->receiver = r; 
    c->method = method_index; 
    c->connectionType = type; 
    c->argumentTypes = types; 
    c->nextConnectionList = 0; 
QObjectPrivate::get(s)->addConnection(signal_index, c); 
  • 信号的发射,就是借助QMetaObject::activate() 来依次处理前面那个Connection列表总的项

do { 
        QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; 
        if (!c) continue; 
        // We need to check against last here to ensure that signals added  
        // during the signal emission are not emitted in this emission. 
        QObjectPrivate::Connection *last = connectionLists->at(signal_index).last;
 
       do { 
            if (!c->receiver) 
                continue; 
             QObject * const receiver = c->receiver;

在该过程中:

  • 如果是直接连接,则通过 QMetaObject::metacall() 直接调用
  • 如果是队列连接,则post一个QMetaCallEvent事件,稍后通过事件派发,该事件的处理函数负责通过 QMetaObject::metacall() 调用相应的槽函数【注意,小心此时槽函数的执行顺序】

注意:此处的代码片段是Qt4的,而Qt5.0 中由于引入了新式的信号和槽语法,对应部分源码有较大变化。

参考

  • http://doc.qt.nokia.com/4.6/signalsandslots.html

  • http://doc.qt.nokia.com/4.5/signalsandslots.html


相关文章:

  • 如何隐藏 video 元素的下载按钮
  • 【Android】自动提示匹配之AutoCompleteTextView
  • 9、ABPZero系列教程之拼多多卖家工具 拼团提醒类库封装
  • 【Android】时间与日期Widget(DatePicker 与 TimePicker)
  • 表单
  • 面试题——二维数组中的查找
  • 使用java poi解析表格
  • 【Android】如何查看每个方法所花费的时间从而进行Performance的调优
  • docker-compose命令
  • 你还在迭代和递归吗?
  • 受欢迎的牛
  • appium自动化安装(一)
  • Template Method模板方法
  • UVA 10603 倒水问题
  • 程序员编程艺术第二十六章:基于给定的文档生成倒排索引(含源码下载)
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 《Java编程思想》读书笔记-对象导论
  • Android系统模拟器绘制实现概述
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • ES6语法详解(一)
  • gitlab-ci配置详解(一)
  • JavaScript-Array类型
  • js面向对象
  • Linux各目录及每个目录的详细介绍
  • python 装饰器(一)
  • Spring框架之我见(三)——IOC、AOP
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • Vue 动态创建 component
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 删除表内多余的重复数据
  • nb
  • #define,static,const,三种常量的区别
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (MATLAB)第五章-矩阵运算
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (二)windows配置JDK环境
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (六)c52学习之旅-独立按键
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Framework .NET Core与 .NET 的区别
  • .NET 设计一套高性能的弱事件机制
  • .net 使用ajax控件后如何调用前端脚本
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET上SQLite的连接
  • :中兴通讯为何成功
  • @Autowired标签与 @Resource标签 的区别
  • @DataRedisTest测试redis从未如此丝滑
  • [《百万宝贝》观后]To be or not to be?
  • [ACTF2020 新生赛]Include
  • [BIZ] - 1.金融交易系统特点
  • [BZOJ1060][ZJOI2007]时态同步 树形dp
  • [CTO札记]如何测试用户接受度?