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