Qt 4.5 - 发射信号是一个函数调用还是线程,它是否会阻塞?

46

我不确定Qt 4.5中信号/槽机制的性质。当一个信号被发射时,它是一个阻塞的函数调用还是一个线程?请说明。

emit GrabLatestData();

// proceed with latest data

在进入下一行代码之前,所有信号/槽链都会被解决吗?

3个回答

57
这取决于情况。根据文档的说法:
当信号被发射时,与之连接的槽通常会立即执行,就像普通函数调用一样。在此期间,信号和槽机制完全独立于任何 GUI 事件循环。只有在所有槽都返回后,才会执行 emit 语句后面的代码。如果使用排队连接,情况略有不同;在这种情况下,紧随 emit 关键字后面的代码将立即继续执行,而槽稍后将被执行。
因此,在正常情况下,它将是同步和阻塞的,而使用排队连接时,它将是异步且非阻塞的。

12
请注意,默认情况下:同一线程中的对象之间的连接是直接的(同步的),不同线程中的对象之间的连接是排队的。如果您考虑一下,这是相当合乎逻辑的。 - quark
1
@quark 这并不完全正确。对象是否在同一个线程中并不重要,重要的是发出信号的线程是否与接收对象所在的线程相同。Qt文档甚至也犯了这个错误。来源:跨线程使用信号和槽。我认为Qt的行为是合理的。 - Jordan Miner

31
最大的问题是你无法知道。也就是说,如果你从类的角度来看待问题。当你发射信号时,你不知道会发生什么:
  • 如果没有人连接到信号,则不会发生任何事情
  • 如果同一线程的某个人使用除Qt :: QueuedConnection之外的任何类型进行连接,则调用将被阻塞
  • 如果同一线程的某个人使用Qt :: QueuedConnection进行连接,则调用将是非阻塞的
  • 如果来自不同线程的某人使用Qt :: DirectConnection(在这种情况下,请非常小心!)或Qt :: BlockingQueuedConnection进行连接,则调用将被阻塞
  • 如果来自不同线程的某个人使用Qt :: AutoConnection或Qt :: QueuedConnection进行连接,则调用将是非阻塞的

如果多个对象连接到信号,那么要知道会发生什么就更加困难。在这种情况下,有些槽可能已经运行,而其他槽仍然在队列中。 顺便提一下,非阻塞连接中没有涉及线程。只需要在接收对象的线程的事件循环中发布一个事件。


11

laalto的回答是正确的。不过还有一点:如果所有的QObjects都属于同一个线程,并且您没有手动指定排队连接,则与信号连接的槽函数的执行是同步的 - 在“emit”语句之后的下一行代码执行之前,所有处理都将完成。因为这是最常见的情况,所以通常对您的问题的答案是“是”。

关于跨多个线程的信号和槽的文档可能对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接