我遇到Qt信号问题。
我不明白DirectConnection
和QueuedConnection
是如何运作的?
如果有人会解释何时使用这些内容(示例代码将不胜感激),我将感激不尽。
答案 0 :(得分:76)
除非您使用具有不同线程亲和力的对象,否则您不会看到太多差异。假设您有QObject A
和B
,它们都连接到不同的线程。 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的回答:
声明“除非您使用具有不同线程亲和力的对象,否则您将看不到太多差异”错误;
在同一个线程内向直接连接发出信号将立即执行该槽,就像一个简单的函数调用一样。
向同一线程内的排队连接发出信号会将调用排入线程事件循环,因此执行将始终发生延迟。
答案 2 :(得分:0)
雅各布的答案很棒。我想在嵌入式编程中添加一个比较示例。
来自嵌入式RTOS / ISR背景,在任务之间查看Qt的DirectConnection与ISR的抢占行为和Qt的QueuedConnection到RTOS中的排队消息的相似性是有帮助的。
附注:来自嵌入式背景,我很难不在编程中定义行为。我从不把论点留作Auto,但这只是个人意见。我更喜欢明确写出所有内容,而且有时会变得困难!