我在使用 Qt 信号时遇到问题。
我不明白如何DirectConnection
工作QueuedConnection
?
如果有人能解释何时使用其中的哪一个(示例代码将不胜感激),我将不胜感激。
我在使用 Qt 信号时遇到问题。
我不明白如何DirectConnection
工作QueuedConnection
?
如果有人能解释何时使用其中的哪一个(示例代码将不胜感激),我将不胜感激。
除非您使用具有不同线程关联性的对象,否则您不会看到太大的差异。假设您有 QObjectsA
并且B
它们都附加到不同的线程。 A
有一个信号叫做somethingChanged()
并且B
有一个槽叫做handleChange()
.
如果您使用直接连接
connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );
该方法handleChange()
实际上将在A
's 线程中运行。基本上,就好像发出信号“直接”调用 slot 方法一样。如果B::handleChange()
不是线程安全的,这可能会导致一些(难以定位)错误。至少,您错过了额外线程的好处。
如果您将连接方法更改为Qt::QueuedConnection
(或者,在这种情况下,让 Qt 决定使用哪种方法),事情会变得更有趣。假设B
' 的线程正在运行一个事件循环,发出信号将向B
' 的事件循环发布一个事件。事件循环将事件排队,并最终在控制权返回时调用 slot 方法(它是事件循环)。这使得在 Qt 中处理线程之间的通信变得非常容易(再次假设您的线程正在运行它们自己的本地事件循环)。您不必担心锁等问题,因为事件循环会序列化插槽调用。
注意:如果您不知道如何更改 QObject 的线程关联,请查看QObject::moveToThread
. 那应该让你开始。
编辑
我应该澄清我的开场白。如果您指定一个排队连接,它确实会有所不同——即使对于同一线程上的两个对象也是如此。该事件仍被发布到线程的事件循环中。因此,方法调用仍然是异步的,这意味着它可以以不可预知的方式延迟(取决于循环可能需要处理的任何其他事件)。但是,如果您不指定连接方法,直接方法将自动用于同一线程上的对象之间的连接(至少在 Qt 4.8 中是这样)。
除了雅各布罗宾斯回答:
声明“除非您使用具有不同线程关联的对象,否则您不会看到太大的区别”是错误的;
向同一线程内的直接连接发出信号将立即执行该槽,就像一个简单的函数调用一样。
向同一线程中的排队连接发出信号会将调用排队到线程事件循环中,因此执行将始终延迟。
雅各布的回答很棒。我只想在嵌入式编程中添加一个比较示例。
来自嵌入式 RTOS/ISR 背景,看到 Qt 的 DirectConnection 与 ISR 的抢占行为和 Qt 的 QueuedConnection 与任务之间的 RTOS 中的队列消息的相似性是有帮助的。
Side note: Coming from an Embedded background, it's difficult for me to not define the behavior in the programming. I never leave the argument as Auto, but that is just a personal opinion. I prefer everything to be explicitly written, and yes that gets difficult at times!