在执行插槽期间断开所有信号插槽连接是否会阻止所有后续插槽被调用?

时间:2011-05-13 13:19:41

标签: qt signals-slots

假设我有一个Qt应用程序,我有这样的东西:

connect(A, SIGNAL(a()), B, SLOT(b1()));
connect(A, SIGNAL(a()), B, SLOT(b2()));
...
void B::b1() {
  A->disconnect();
}

如果发出a(),那么在B::b2()中断开所有插槽后,仍会调用插槽B::b1(),因为它们都响应相同的信号吗?假设两个对象都存在于同一个线程中,因此我们有直接连接。

我知道disconnect()会断开与A的所有信号连接,但我不确定发射是否只调度要调用的b1和b2插槽,然后调用它们,以便更改连接直到两个插槽(因此发射)返回时才有效。所以它可以实现如下:

emit:
  make temprorary copy of signal's slot table
  foreach element in temporary slot table: call

disconnect:
  clear signal's slot table

否则,您可能会遇到数据结构完整性问题。

2 个答案:

答案 0 :(得分:5)

快速实验表明未调用第二个插槽。

但是,我不确定这是否是Qt所承诺的。

Qt确实记录了在连接接收器的迭代过程中进行的某些检查,但是这是非常宽松和非特定的(我的短搜索中没有发现任何更好的东西);来自http://doc.qt.io/qt-5/signalsandslots.html

  

这是定位连接对象所需的开销,以安全地迭代所有连接(即检查后续接收器在发射期间是否未被破坏)

因此,他们松散地记录了在发出信号时进行的某些检查,例如接收器是否已被破坏。我认为检查连接是否已经断开似乎是一种类似的情况,但如果明确记录下来会很好。

因为听起来这对你来说是一个问题(你希望所有的信号都通过,对吧?),你可以通过确保信号到插槽b1()来解决这个问题。最后连接。 Qt确实承诺将按连接顺序通过信号调用插槽,因此如果您安排将断开连接的插槽作为最后一个插槽,则可以看到所有其他插槽。

我不知道这可能是多么容易安排,但是一个对象将从另一个对象的槽函数内部断开所有内容似乎有点奇怪(所以可能还有其他一些可以解决这个问题的重构)

如果这些都不可接受,那么为A的具有您需要的行为的信号提供代理对象并不会太难。会有一个:

connect(A, SIGNAL(a()), proxy_obj, SLOT(proxy_slot()));

将A的信号连接到代理,然后B可以连接到代理的信号(当代理的插槽被调用时,代理将发出信号):

connect(proxy_obj, SIGNAL(a()), B, SLOT(b1()));
connect(proxy_obj, SIGNAL(a()), B, SLOT(b2()));

由于A的断开连接不会影响代理与B的连接,因此代理将确保在发出信号A->a()时调用所有B的插槽。

class A_proxy : public QObject
{
    Q_OBJECT
public slots:
    void proxy_slot() {
        emit a();
    }

signals:
    void a();
};

答案 1 :(得分:-3)

disconnect reference page回答了您的问题。

这取决于你如何调用它,以及你调用它的方式(没有任何参数),它将断开对象A上的所有信号,因此断开连接后不会调用插槽B:b2。