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
专业化),其目的是读取系统事件。因此,对于不同的平台,它存在QEventDispatchWin
、QEventDispatchUnix
、QEventDispatchSymbian
等等。对于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).
如果调用了quit
或exit
,它将结束当前的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 和其他线程+事件循环的主要内容,如果未能解决你的问题,请参考以下文章
事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)