PyQt 信号:在 disconnect() 之后,触发的信号是否仍能正常工作?

PyQt signals: will a fired signal still do its job after a disconnect()?

我正在处理一个应用程序,在该应用程序中会触发许多信号,然后重新连接。我将详细解释该应用程序的工作原理,以及我的困惑是从哪里开始的。


1。重新连接信号

在我的应用程序中,我经常重新连接信号。为此,我将使用以下静态函数,取自@ekhumoro 的回答(并稍作修改)来自 post: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)


2。申请

想象一下函数 emitterFunc(self) 遍历对象列表。在每次迭代中,该函数将 mySignal 连接到一个对象,触发信号,然后在下一个迭代步骤开始时再次断开连接 mySignal。发射的信号还携带一些有效负载,例如对象 Foo().


编辑:


3。信号槽机制的心理形象

随着时间的推移,我已经在脑海中形成了信号槽机制如何工作的印象。我想象一个 Signal-Slot 引擎 吸收所有发射的信号并将它们放入队列中。每个信号等待轮到它。当时间准备就绪时,引擎将给定的信号传递给适当的处理程序。为了正确地做到这一点,引擎有一些 'bookkeeping' 工作来确保每个信号都在正确的插槽中结束。


4。 Signal-Slot 引擎的行为

假设我们正处于第 nth 迭代步骤。我们将 self.mySignal 连接到 object_n。然后我们用它的有效载荷发射信号。几乎在这样做之后,我们立即断开连接并建立到 object_n+1 的新连接。在我们断开连接的那一刻,发射的信号可能还没有完成它的工作。我可以想象 Signal-Slot 引擎的三种可能行为:


5。我的问题

我的第一个问题现在已经很明显了。正确的 Signal-Slot 引擎行为是什么?我希望是第三种选择。

作为第二个问题,我想知道给定的心理图像在多大程度上是正确的。例如,我可以依赖信号按顺序离开队列吗?这个问题不太重要——它对我的申请当然不重要。

第三个问题与时间效率有关。重新连接到另一个处理程序是否耗时?知道第一个问题的答案后,我将继续构建应用程序,我可以自己测量重新连接时间。所以这个问题不是那么重要。但是,如果您无论如何都知道答案,请分享:-)

我将从你的第二个问题开始,说你的心理形象部分正确,因为涉及队列,但是不总是。发出信号时,可以通过三种可能的方式调用连接的插槽,其中两种使用事件队列(QMetaCallEvent 即时实例化并使用 QCoreApplication 的方法发布postEvent,其中事件目标是插槽持有者,或者信号接收器,如果你愿意的话)。第三种情况是直接调用,所以发出信号就像调用插槽一样,没有任何东西排队。

现在第一个问题:在任何情况下,当发出信号时,都会遍历一个连接列表(属于信号发射器),然后调用插槽另一个使用上面提到的三种方法之一。每当连接建立或断开时,列表都会更新,但这必然发生在信号发出之前或之后。简而言之:在信号发出后,成功阻止对已连接插槽的调用的机会很小,至少不会断开与 disconnect() 的连接。所以我会将 [OPTION 3] 标记为正确。

如果您想深入了解,请从 ConnectionType enum documentation 开始,其中对三种基本连接类型(直接、排队和阻塞排队)进行了很好的解释。 连接类型 可以指定为 QObject 方法 connect 的第五个参数,但是,正如您将从上述链接文档中了解到的那样,通常是Qt自己选择最适合情况的连接类型。剧透:涉及线程:)

关于第三个问题:我手头没有基准测试可以展示,所以我会给出所谓的主要基于意见答案,以恕我直言开头的那种答案。我认为 signal/slot 领域是 保持简单 规则统治的领域之一,而你的 reconnect 模式似乎使事情变得比他们需要的复杂得多。正如我在上面所暗示的,建立连接后,连接对象将附加到列表中。当信号发出时,所有连接的插槽将以某种方式被调用,一个接一个。因此,为什么不先连接所有项目,然后发出信号,然后将它们全部断开,而不是在循环中的每个循环中 disconnect/reconnect/emit 呢?

我希望我的(冗长而冗长的)回答对您有所帮助。好读。