查看完整版本: [-- 杜绝Qt信号槽嵌套问题 --]

QTCN开发网 -> Qt 作品展 -> 杜绝Qt信号槽嵌套问题 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

samhuilong 2017-03-09 17:17

杜绝Qt信号槽嵌套问题

随意使用信号槽是很危险的一件事情,如果不加限制,项目的代码量多了,一旦出现了槽的重复调用,想要修复这个BUG,非常困难。
原则上来讲,只要接受信号的槽不继续发信号,就不会造成嵌套。但是项目大了后,这个基本不可能得到保证。
1.不可能在槽里面调用的所有的函数都一层一层去查看有没有继续发信号
2修改一个需求,槽函数里面增加一个函数调用,还要先去查看这个函数有没有发信号,这个不现实
3团队之间不同模块是不同的程序员维护的,不能保证所有人都严格遵守槽函数里面不发信号这个规则

附上demo示例:[attachment=16624]
1 MessageCenter负责模块之间的通信,转发模块之间的消息时加锁,防止模块之间的消息嵌套。
2 信号槽来实现一个模块内部的通信,其中AutoSlotsLocker和SlotsLocker类控制信号槽的加锁,防止信号槽的嵌套。





stlcours 2017-03-09 20:34
我在刚学Qt的时候,就见到说要避免信号槽的嵌套使用,所以这应该是Qt程序员最起码的素质

楼主的代码也不错,但是由于内部只包含两个Module,所以可以这样使用:
            for(size_t i = 0; i < m_lstClient.size();++i)
            {                
                if (m_lstClient != sender)
                {
                    m_lstClient->NotifyMessage(sender, mType, eventArgs);
                }
            }
否则应该先整体寻找,找到了以后也只能发送一遍。

lsyzsl 2017-03-10 09:59
全部看了一遍,竟然没看出来哪里杜绝了。

samhuilong 2017-03-10 10:15
lsyzsl:全部看了一遍,竟然没看出来哪里杜绝了。[表情] (2017-03-10 09:59)

1 模块之间通过MessageCenter通信,模块1给模块2发消息,模块2接到消息继续给模块1发消息,由于MessageCenter加锁了,所以第二个消息直接屏蔽了,不会造成模块之间的消息嵌套。

2 SlotsLocker是用来给槽函数加锁的,所有的槽函数第一行都必须先判断锁,如果调用函数不希望触发槽,只要给SlotsLocker上锁,就保证不会触发槽了。
如果所有的槽函数里面第一步判断锁,第二步给SlotsLocker上锁,那么如果信号触发了槽,槽里面继续发信号,其他的槽就直接return了,相当于屏蔽了槽函数里面的信号,不会造成信号槽的嵌套。(AutoSlotsLocker的作用就是在槽函数执行完成后自动解除锁)


lsyzsl 2017-03-12 20:33
samhuilong:1 模块之间通过MessageCenter通信,模块1给模块2发消息,模块2接到消息继续给模块1发消息,由于MessageCenter加锁了,所以第二个消息直接屏蔽了,不会造成模块之间的消息嵌套。
2 SlotsLocker是用来给槽函数加锁的,所有的槽函数第一行都必须先判断锁,如果调用函数不希望触发 .. (2017-03-10 10:15) 

在项目中使用的情况可能不仅仅是模块一和模块二这么少,有可能还有模块三、四、五,用你这种方法可以么?

samhuilong 2017-03-13 08:44
没问题,只要把你想添加的模块注册到MessageCenter,然后这个模块接收自己需要的消息更新。MessageCenter是广播式的发送的。
我现在开发的项目,客户端代码量也几十万了,从来没出现过信号槽嵌套问题。

thefront 2017-03-16 10:59
贴主好人啊。谢谢!

return 2017-03-16 13:48
实用技术

1003780259 2017-03-22 09:37
感谢!!!开源精神!!

pinklau 2020-02-25 11:17
感谢分享,应该可以解决类似的问题了

zhpic 2020-08-31 10:04
不错,值得学习。虽然过去这么久了,但还是很不错的。


查看完整版本: [-- 杜绝Qt信号槽嵌套问题 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled