我正在处理一个应用程序,其中许多信号被触发,然后重新连接。我将详细解释该应用程序的工作原理,以及我的困惑开始的地方。
在我的应用程序中,我经常重新连接信号。我将使用以下静态函数,取自@ekhumoro的答案(并稍加修改)来自这篇文章:PyQt Widget connect() and disconnect()
def reconnect(signal, newhandler):
while True:
try:
signal.disconnect()
except TypeError:
break
if newhandler is not None:
signal.connect(newhandler)
想象一下,函数emitterFunc(self)
循环遍历一个对象列表。在每次迭代时,函数将mySignal
连接到对象,触发信号,然后在下一个迭代步骤开始时再次断开mySignal
。触发信号还携带一些有效载荷,例如对象Foo()
。
修改
上面显示的设计简化了很多。在最终设计中,信号发射器和接收槽可能在不同的线程中运行。
由于导致我们误入歧途的原因,我不能一次连接所有对象,发出信号,最后将它们全部断开。我必须逐个循环,执行connect-emit-disconnect过程。
再次由于导致我们走得太远的原因,我不能直接调用这些插槽。
随着时间的推移,我已经建立了信号槽机制如何工作的心理图像。我想象一个信号槽引擎吸收所有发射信号并将它们放入队列中。每个信号等待轮到他们。当时间准备就绪时,引擎将给定信号传递给适当的处理程序。为了正确地做到这一点,引擎有一些'簿记'工作,以确保每个信号在正确的插槽中结束。
想象一下,我们正处于n th 迭代步骤。我们将self.mySignal
与 object_n 相关联。然后我们用它的有效载荷发射信号。在执行此操作后,我们几乎立即断开连接并建立与 object_n + 1 的新连接。目前我们打破了连接,被发射的信号可能还没有完成它的工作。我可以想象Signal-Slot引擎的三种可能行为:
[选项1]引擎注意到连接已断开,并从其队列中丢弃sig_n
。
[选项2]引擎注意到连接已重新建立到另一个处理程序,并将sig_n
发送到 object_n + 1 的处理程序(只要它到达队列的前面。
[选项3]引擎不会更改sig_n
的任何内容。在被解雇时,它被用于 object_n 的处理程序,并且它将在那里结束。
我的第一个问题现在非常明显。什么是正确的信号槽引擎行为?我希望这是第三种选择。
作为第二个问题,我想知道给定的心理图像在多大程度上是正确的。例如,我可以依赖于按顺序退出队列的信号吗?这个问题不太重要 - 这对我的申请来说当然不是很重要。
第三个问题与时间效率有关。是否重新连接到另一个处理程序耗时?一旦我知道第一个问题的答案,我将继续构建应用程序,我可以自己测量重新连接时间。所以这个问题不是那么重要。但如果你知道答案,请分享: - )
答案 0 :(得分:2)
我会从第二个问题开始,说你的心理图像部分正确,因为涉及队列,但并非总是如此。当发出信号时,有三种可能的方式来调用连接的插槽,其中两个使用事件队列(动态实例化QMetaCallEvent
并使用QCoreApplication
的方法发布postEvent
,其中事件目标是插槽持有者,或者信号接收器,如果您愿意的话)。第三种情况是直接调用,因此发出信号就像调用插槽一样,没有任何内容排队。
现在到第一个问题:在任何情况下,当发出信号时,遍历一个连接列表(属于信号发射器)并且使用其中一个连接调用插槽上面提到的三种方法。无论何时建立连接或断开连接,列表都将更新,但这必须在发出信号之前或之后发生。简而言之:在发出信号后成功阻止对连接槽的调用的机会很小,至少不会破坏与disconnect()
的连接。所以我会将[OPTION 3]
标记为正确。
如果您想进一步深入挖掘,请从ConnectionType enum documentation开始,其中详细解释了三种基本类型的连接(直接,排队和阻塞排队)。可以将连接类型指定为QObject
方法connect
的第五个参数,但是,正如您将从上述链接文档中学习的那样,通常是Qt本身选择最适合的情况的连接类型。剧透:涉及线程:)
关于第三个问题:我手边没有基准测试显示,所以我会给出一个所谓的主要基于意见的答案,这种答案开始与恕我直言。我认为 signal / slot 域是 keep-it-simple 规则的规则之一,而你的重新连接模式似乎使事情变得比他们需要的复杂得多。如上所述,当建立连接时,连接对象将附加到列表中。当发出信号时,将以某种方式一个接一个地调用所有连接的插槽。因此,不是在循环中的每个循环中断开/重新连接/发出,为什么不先连接所有项目,然后发出信号,然后将它们全部断开?
我希望我的(长期的,可能是tldr)答案有所帮助。好读。