Qt 如何在同一个 EventLoop 中处理事件和信号

Posted

技术标签:

【中文标题】Qt 如何在同一个 EventLoop 中处理事件和信号【英文标题】:How Qt Handle Events and Signal in Same EventLoop 【发布时间】:2020-07-21 10:36:55 【问题描述】:

我不明白 qt 如何在同一个事件循环中处理事件(例如定时器事件、套接字事件等)和信号。据我了解,定时器和套接字事件是通过 select 系统调用(在 Unix 等操作系统中)处理的。

由于 select 系统调用,事件循环如何在睡眠时处理信号。

【问题讨论】:

你在说什么睡觉?您所在的上下文中的事件循环不会休眠,直到您自己在代码中调用长阻塞操作。阅读这个关于事件的好答案并用 Qt ***.com/a/3794944/4149835 发出信号 感谢您的回答。我读了那个答案,但我不明白它如何使用相同的 select 系统调用处理计时器事件、套接字事件和信号。它可以使用文件描述符和选择的超时参数来处理套接字事件和计时器事件。但是 Qt 信号如何通知选择调用。 【参考方案1】:

在 Qt 中,信号用于调用槽。当你发出一个信号时,粗略地说,调用对应的槽只有两种选择:

    直接槽调用。这可以被认为是用仅具有插槽调用的线路发出的信号替换线路。事件循环不用于处理此信号本身。 延迟槽调用。在这种情况下,信号将被转换为事件,并且该事件将被发布到接收者事件循环中(事件在接收者对象所在线程的事件循环中排队)。从现在开始,对于处理接收者事件循环,它是信号还是事件都没有区别。该事件将被事件循环拾取,并在稍后的某个时间引起插槽调用。

来自 Qt 文档:https://doc.qt.io/qt-5/signalsandslots.html#signals

当一个信号发出时,连接到它的槽通常是 立即执行,就像正常的函数调用一样。当这 发生时,信号和槽机制完全独立于任何 GUI 事件循环。在发出语句之后执行代码 将在所有插槽返回后发生。情况略显 使用排队连接时有所不同;在这种情况下,代码 在 emit 关键字之后将立即继续,并且插槽 将稍后执行

就理解事件循环而言,事件循环只是在每次迭代时处理来自事件队列的一个事件的循环。 简而言之,这可以表示如下:

QQueue<QEvent> eventQueue; // Events (and pending slot calls as well) are added to this queue
...

// How an event loop works (schematically):
while(event = eventQueue.dequeue())

    do_what_the_event_wants_or_ignore_it(event);

另请阅读https://wiki.qt.io/Threads_Events_QObjects

【讨论】:

我想知道它如何仅通过一个选择系统调用来复用 io 事件、定时器事件和信号事件。那么它如何在主事件循环等待 IO 事件时处理信号事件。正如我从 qeventdispatcher_unix.cpp 文件中了解到的那样,它通过 eventfd 系统调用唤醒主事件循环并处理信号事件 @overlord 那么您需要提供您认为合并事件的代码部分 @overlord 请注意您的问题的标题是“Qt 如何在同一 EventLoop 中处理事件和信号”

以上是关于Qt 如何在同一个 EventLoop 中处理事件和信号的主要内容,如果未能解决你的问题,请参考以下文章

QT事件循环

Netty搬运工 EventLoop与Bootstrap

Spark中的事件循环处理器EventLoop

前端中的事件循环eventloop机制

REDIS事件之EventLoop

构建一个基于消息驱动的Eventloop线程模型