我刚刚在Qt 4.6中发现了有趣的排队连接行为:
首先排队连接:
connect(someSender, SIGNAL(completed()), this, SLOT(handleCompletion()), Qt::QueuedConnection)
然后someSender发送信号:
emit completed()
在接收信号之前(因为它在队列中),我断开信号:
disconnect(someSender, SIGNAL(completed()), this, SLOT(handleCompletion())
仍然,在下一个eventloop迭代时调用handleCompletion槽。我可以通过在正确的点使用someSender-> blockSignals(true)来防止这种情况发生,但是如果没有提到一些布尔标志来禁用插槽的功能,那就太糟糕了。
特别是,我感到惊讶的是Qt文档中没有提到这种行为(至少我没有找到)。
最后一个问题:是否有任何明智的方法可以避免这种情况发生?
答案 0 :(得分:8)
我认为Qt的行为方式最直观。
执行emit completed()
时,信号立即激活或排队所有连接的插槽是有意义的。如果排队的插槽可能因断开连接而排队,则更难以理解,并且更容易出现竞争条件。另外,考虑更复杂的情况:例如因此,如果断开连接将其从队列中删除,重新连接会将其重新放回吗?
如果它按照你预期的方式运行,那么代替这个问题就会出现“Qt :: QueuedConnection问题,断开连接后信号没有传递”。
至于避免这种情况的合理方法:您应该重新设计代码,以便发送方和接收方都不必关心信号是直接连接还是排队。我建议发送方和接收方都不要调用QObject::connect
,这是由第三类完成的。目前尚不清楚这是否能完全解决您的问题,这取决于您在disconnect
执行的地点和原因。