Qt信号(QueuedConnection和DirectConnection)

时间:2013-02-24 12:07:50

标签: c++ qt qthread qt-signals

我遇到Qt信号问题。

我不明白DirectConnectionQueuedConnection是如何运作的?

如果有人会解释何时使用这些内容(示例代码将不胜感激),我将感激不尽。

3 个答案:

答案 0 :(得分:76)

除非您使用具有不同线程亲和力的对象,否则您不会看到太多差异。假设您有QObject AB,它们都连接到不同的线程。 A有一个名为somethingChanged()的信号,B有一个名为handleChange()的广告位。

如果您使用直接连接

connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );

方法handleChange()实际上将在A的主题中运行。基本上,就好像发出信号“直接”调用插槽方法一样。如果B::handleChange()不是线程安全的,这可能会导致一些(难以定位)错误。至少,你错过了额外线程的好处。

如果您将连接方法更改为Qt::QueuedConnection(或者,在这种情况下,让Qt决定使用哪种方法),事情会变得更有趣。假设B的线程正在运行事件循环,发出信号会将事件发布到B的事件循环。事件循环对事件进行排队,并最终在控制返回时调用slot方法(它是事件循环)。这使得处理Qt中线程之间的通信非常容易(同样,假设您的线程正在运行它们自己的本地事件循环)。您不必担心锁等,因为事件循环序列化了插槽调用。

注意:如果您不知道如何更改QObject的线程关联,请查看QObject::moveToThread。这应该让你开始。

修改

我应该澄清我的开场白。如果指定排队连接 - 即使是同一线程上的两个对象,它确实会有所不同。该事件仍然发布到线程的事件循环中。因此,方法调用仍然是异步的,这意味着它可能以不可预测的方式延迟(取决于循环可能需要处理的任何其他事件)。但是,如果未指定连接方法,则直接方法将自动用于同一线程上的对象之间的连接(至少在Qt 4.8中)。

答案 1 :(得分:22)

除了Jacob Robbins的回答:

声明“除非您使用具有不同线程亲和力的对象,否则您将看不到太多差异”错误;

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

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

QObject based class has a queued connection to itself

答案 2 :(得分:0)

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

来自嵌入式RTOS / ISR背景,在任务之间查看Qt的DirectConnection与ISR的抢占行为和Qt的QueuedConnection到RTOS中的排队消息的相似性是有帮助的。

附注:来自嵌入式背景,我很难不在编程中定义行为。我从不把论点留作Auto,但这只是个人意见。我更喜欢明确写出所有内容,而且有时会变得困难!