Qt Main-Gui 和其他线程+事件循环

Posted

技术标签:

【中文标题】Qt Main-Gui 和其他线程+事件循环【英文标题】:Qt Main-Gui and other thread + events loops 【发布时间】:2013-05-24 15:17:58 【问题描述】:

我正在尝试了解 Qt 的整个内部过程,以及当我使用不同的线程时它是如何工作的。

据我了解(谷歌搜索和探索 Qt 源代码)如下:

每个线程都有一个本地“待处理事件列表”和一个与该列表交互的本地事件循环(如果我调用 exec)。 QCoreApplication::postEvent(obj, e)(obj, e) 对附加到 obj 线程的“待处理事件列表”中。 每个线程都有一个本地“事件调度器”(QAbstractEventDispatcher 专业化),其目的是读取系统事件。因此,对于不同的平台,它存在QEventDispatchWinQEventDispatchUnixQEventDispatchSymbian 等等。对于gui事件,Qt还有QEventDispatchX11(继承自QEventDispatchUnix)、S60(继承自Symbian)等。

考虑到这一切,exec 调用如下:

Thread's `exec`:
 ├ create a QEventLoop object.
 └ call QEventLoop.exec()
   └ call repeatedly eventDispatcher's processEvents with WaitForMoreEvents flag.
     ├ call to QCoreApplication::sendPostedEvents
     ├ while (!pending system events)
     │  ├ read system event
     │  ├ create an appropiate QEvent e and detect its target QObject o.
     │  └ call to QCoreApplication::sendSpontaneousEvent(o, e)
     └ call to QCoreApplication::sendPostedEvents
       (for new generated user events in the previous step).

如果调用了quitexit,它将结束当前的processEvents 调用,exec 返回传递给exit 的值。

需要考虑的几点:

    从不推送/发布系统事件:当它们从系统生成并转换为 QEvents 时,它们会直接发送到其目标对象。 目标对象成员函数 (o.event()) 在发生 processEvent 的同一线程中调用。

现在,疑问:

    既然postEvent是一个静态和线程安全的函数,那么QCoreApplication在这个事件处理系统中扮演什么角色呢? QApplication?为什么它们必须尽快创建? 如果每个线程都有自己的“事件调度器”,为什么 QApplication/QCoreApplication 必须强制获取系统事件?

欢迎对我的假设进行任何更正。

【问题讨论】:

【参考方案1】:

针对您的第二个问题,“如果每个线程都有自己的“事件调度程序”,为什么 QApplication/QCoreApplication 必须强制获取系统事件?”

4.8 文档指出:

"请注意,QCoreApplication::exec() 必须始终从主线程(执行 main() 的线程)调用,而不是从 QThread。在 GUI 应用程序中,主线程也称为 GUI 线程,因为它是唯一允许执行 GUI 相关操作的线程。”

但是关于一般的 QThreads - 您会发现提供的链接将 QThreads 描述为 QObjects,它是线程的包装器。因此,QThreads 与任何其他 QObjects 一样,需要 QCoreApplication 与之交互以协调通知/事件,例如当线程完成时。

http://qt-project.org/forums/viewthread/14806

在 Maya 的文章中,她提供了一个示例,其中任务被分配给 QThread,而不是在 [i.e.使用信号/插槽,不要重载 run() 方法]。这样一来,你就清楚的看到QCoreApplication提供的主事件循环还是起到了至关重要的作用。

正如您可能已经知道的那样,在本网站上已经围绕 QThreads 主题展开了大量讨论 - 而 Qt4 的文档也很完善......不能对 Qt5 说同样的话 =(

【讨论】:

抱歉,这么晚才将您的回复标记为答案。直到今天我才意识到。

以上是关于Qt Main-Gui 和其他线程+事件循环的主要内容,如果未能解决你的问题,请参考以下文章

QT中的线程与事件循环理解

Qt 的线程与事件循环

Qt 的线程与事件循环

事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)

将使用事件循环的 C++/Qt 线程转换为使用 Dispatchers 的 C#(或 java)线程的可能性

在 Qt GUI 事件线程中检测到“我正在运行”