C++ Qt 信号(QueuedConnection 和 DirectConnection)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15051553/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:57:06  来源:igfitidea点击:

Qt signals (QueuedConnection and DirectConnection)

c++qtqthreadqt-signals

提问by Nika

I'm having trouble with Qt signals.

我在处理 Qt 信号时遇到了麻烦。

I don't understand how DirectConnectionand QueuedConnectionworks?

我不明白如何DirectConnectionQueuedConnection工作?

I'd be thankful if someone will explain when to use which of these (sample code would be appreciated).

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

回答by Jacob Robbins

You won't see much of a difference unless you're working with objects having different thread affinities. Let's say you have QObjects Aand Band they're both attached to different threads. Ahas a signal called somethingChanged()and Bhas a slot called handleChange().

除非您使用具有不同线程亲和性的对象,否则您不会看到太大差异。假设您有 QObjectsA并且B它们都附加到不同的线程。 A有一个信号称为somethingChanged()B有一个插槽称为handleChange()

If you use a direct connection

如果您使用直接连接

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

the method handleChange()will actually run in the A's thread. Basically, it's as if emitting the signal calls the slot method "directly". If B::handleChange()isn't thread-safe, this can cause some (difficult to locate) bugs. At the very least, you're missing out on the benefits of the extra thread.

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

If you change the connection method to Qt::QueuedConnection(or, in this case, let Qt decide which method to use), things get more interesting. Assuming B's thread is running an event loop, emitting the signal will post an event to B's event loop. The event loop queues the event, and eventually invokes the slot method whenever control returns to it (it being the event loop). This makes it pretty easy to deal with communication between/among threads in Qt (again, assuming your threads are running their own local event loops). You don't have to worry about locks, etc. because the event loop serializes the slot invocations.

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

Note: If you don't know how to change a QObject's thread affinity, look into QObject::moveToThread. That should get you started.

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

Edit

编辑

I should clarify my opening sentence. It does make a difference if you specifya queued connection - even for two objects on the same thread. The event is still posted to the thread's event loop. So, the method call is still asynchronous, meaning it can be delayed in unpredictable ways (depending on any other events the loop may need to process). However, if you don't specify a connection method, the direct method is automatically used for connections between objects on the same thread (at least it is in Qt 4.8).

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

回答by t_3

in addition to Jacob Robbins answer:

除了雅各布罗宾斯的回答:

the statement "You won't see much of a difference unless you're working with objects having different thread affinities" is wrong;

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

emitting a signal to a direct connection within the same thread will execute the slot immediately, just like a simple function call.

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

emitting a signal to a queued connection within the same thread will enqueue the call into the threads event loop, thus the execution will alwayshappen delayed.

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

QObject based class has a queued connection to itself

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

回答by user3934527

Jacob's answer is awesome. I'd just like to add a comparative example to Embedded Programming.

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

Coming from an embedded RTOS/ISR background, it was helpful to see the similarities in Qt's DirectConnection to Preemptive behavior of the ISRs and Qt's QueuedConnection to Queued Messages in an RTOS between tasks.

来自嵌入式 RTOS/ISR 背景,看到 Qt 的 DirectConnection 与 ISR 的抢占行为和 Qt 的队列连接到任务之间的 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!

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