Qt 信号(QueuedConnection 和 DirectConnection)
我在处理 Qt 信号时遇到问题.
I'm having trouble with Qt signals.
我不明白 DirectConnection
和 QueuedConnection
是如何工作的?
I don't understand how DirectConnection
and QueuedConnection
works?
如果有人能解释何时使用其中的哪一个(示例代码将不胜感激),我将不胜感激.
I'd be thankful if someone will explain when to use which of these (sample code would be appreciated).
推荐答案
除非您使用具有不同线程亲缘关系的对象,否则您不会看到太大差异.假设您有 QObjects A
和 B
并且它们都附加到不同的线程.A
有一个名为 somethingChanged()
的信号,B
有一个名为 handleChange()
的槽.
You won't see much of a difference unless you're working with objects having different thread affinities. Let's say you have QObjects A
and B
and they're both attached to different threads. A
has a signal called somethingChanged()
and B
has a slot called handleChange()
.
如果您使用直接连接
connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );
方法 handleChange()
将实际运行在 A
的线程中.基本上,就好像发出信号直接"调用插槽方法一样.如果 B::handleChange()
不是线程安全的,这可能会导致一些(难以定位)错误.至少,您错过了额外线程的好处.
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.
如果您将连接方法更改为 Qt::QueuedConnection
(或者,在这种情况下,让 Qt 决定使用哪种方法),事情会变得更有趣.假设 B
的线程正在运行一个事件循环,发出信号将向 B
的事件循环发送一个事件.事件循环对事件进行排队,并最终在控制权返回给它时调用 slot 方法(它是事件循环).这使得处理 Qt 中线程之间的通信变得非常容易(再次假设您的线程正在运行它们自己的本地事件循环).您不必担心锁定等问题,因为事件循环会序列化槽调用.
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.
注意:如果您不知道如何更改 QObject 的线程关联,请查看 QObject::moveToThread
.这应该会让你开始.
Note: If you don't know how to change a QObject's thread affinity, look into QObject::moveToThread
. That should get you started.
编辑
我应该澄清一下我的开场白.如果您指定一个排队连接,它确实会有所不同――即使对于同一线程上的两个对象.该事件仍然发布到线程的事件循环.因此,方法调用仍然是异步的,这意味着它可以以不可预测的方式延迟(取决于循环可能需要处理的任何其他事件).但是,如果不指定连接方法,同一个线程上的对象之间的连接会自动使用直接方法(至少在Qt 4.8中是这样).
I should clarify my opening sentence. It does make a difference if you specify a 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).
相关文章