Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt信号(QueuedConnection和DirectConnection)_C++_Qt_Qthread_Qt Signals - Fatal编程技术网

C++ Qt信号(QueuedConnection和DirectConnection)

C++ Qt信号(QueuedConnection和DirectConnection),c++,qt,qthread,qt-signals,C++,Qt,Qthread,Qt Signals,我的Qt信号有问题 我不明白DirectConnection和QueuedConnection是如何工作的 如果有人能解释一下什么时候使用其中的哪一个,我将不胜感激。除非您使用的对象具有不同的线程亲和力,否则您不会看到太大的差异。假设您有QObjectsA和B,它们都连接到不同的线程A有一个名为somethingChanged()的信号,B有一个名为handleChange()的插槽 如果使用直接连接 connect( A, SIGNAL(somethingChanged()), B, SLOT

我的Qt信号有问题

我不明白
DirectConnection
QueuedConnection
是如何工作的


如果有人能解释一下什么时候使用其中的哪一个,我将不胜感激。

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

如果使用直接连接

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

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

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

编辑


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

除了Jacob Robbins回答:

“除非处理具有不同线程亲缘关系的对象,否则不会看到太大的差异”的说法是错误的

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

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


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

来自嵌入式RTOS/ISR背景,了解Qt的DirectConnection与ISR抢占行为的相似性,以及Qt的QueuedConnection与任务间RTOS中排队消息的相似性是很有帮助的


旁注:来自嵌入式背景,我很难不定义编程中的行为。我从不把这个论点当作自动的,但那只是个人的观点。我喜欢所有的东西都要明确地写出来,是的,这有时会变得很困难

看到了吗?关于这些,你具体不了解什么?你的问题可以归结为“信号和插槽如何工作”,没有这个问题,这是一个有点宽泛的问题,文档已经很好地涵盖了它。。据我所知,当发送方和接收方在不同的线程中时,应该使用QueuedConnection。例如,我有GUI线程(主线程)和新线程(pThread),它有一个信号,例如void doSomething();接收器是GUI的主线程。所以,我必须使用QueuedConnection,不管我在哪里调用它?(在GUI线程或新线程中,connect命令)谢谢..阅读第一条评论中的文档。除非您试图做一些非常具体的事情,并且完全了解风险,否则根本不要指定连接模式。默认情况下将使用正确的模式(直接用于内部线程,排队用于内部线程)。我现在完全理解信号和插槽,无论如何感谢您提到它。这一点很好。我总是让Qt选择连接方法,除非我有很好的理由选择其中一种…所以当对象在同一线程上时,我会得到直接连接(使用4.8)。如果您强制进行排队连接,这肯定会有所不同。我编辑我的答案是为了澄清。@Jacob那么直接调用handleChange()不是更好吗就像一个普通函数,而不是直接连接情况下的信号槽混淆一样?Cool_Coder:通过sig/槽连接调用该方法的优点是,您不必将对象
B
的知识构建到
a
-您可以让这两个类的用户确定何时应该发生什么
A
发出的
somethingChanged
。这有意义吗?如果我不将
Qt::QueuedConnection
指定为参数,会发生什么?我问这个问题的原因是,在许多地方,指定
Qt::QueuedConnection
或direct是一个可选参数。这是否意味着Qt会自行决定是否“将信号排队或直接调用”?@Game\u of_线程:默认参数为
Qt::AutoConnection
。如果发射器和接收器在同一个线程中,则使用
DirectConnection
。否则,将使用
QueuedConnection
。@Jacobin Robbins请您澄清为什么在使用
Qt::QueuedConnection
时不需要使用锁或同步?即使两个线程共享一些数据(都可以读或写)?或者当线程
A
通过ar传递一些数据时