55

我在使用 Qt 信号时遇到问题。

我不明白如何DirectConnection工作QueuedConnection

如果有人能解释何时使用其中的哪一个(示例代码将不胜感激),我将不胜感激。

4

3 回答 3

94

除非您使用具有不同线程关联性的对象,否则您不会看到太大的差异。假设您有 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 中是这样)。

于 2013-03-13T02:29:59.987 回答
31

除了雅各布罗宾斯回答:

声明“除非您使用具有不同线程关联的对象,否则您不会看到太大的区别”是错误的;

向同一线程内的直接连接发出信号将立即执行该槽,就像一个简单的函数调用一样。

向同一线程中的排队连接发出信号会将调用排队到线程事件循环中,因此执行将始终延迟。

基于 QObject 的类与自身有一个排队连接

于 2013-10-12T12:03:50.493 回答
1

雅各布的回答很棒。我只想在嵌入式编程中添加一个比较示例。

来自嵌入式 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!

于 2017-06-29T15:08:14.693 回答