QT消息/事件循环机制与多线程的关系
关于Qt子线程和消息循环
一、QT消息/事件循环机制
Qt作为一个可视化GUI界面操作系统,是基于事件驱动的,我们程序执行的顺序不再是线性,而是由一个个应用程序内部或外部的事件进行驱动,无事件时便阻塞。这个循环概念类似于while的函数循环,函数体内不断处理用户的输入,类比到事件循环中,用户点击了鼠标、按下了键盘,便被称作为事件。
一般对于带UI窗口的程序来说,“事件”是由操作系统或程序框架在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,计时器触发的时候,都会发出一个相应的事件。我们把“事件循环”的代码 提炼/抽象 如下
function eventloop() {
initialize();
bool shouldQuit = false;
while(false == shouldQuit)
{
var message = get_next_message();
process_message(message);
if (message == QUIT)
{
shouldQuit = true;
}
}
}
机制解释
这样的程序运行流程,我们叫做“事件驱动”式的程序。一般的Qt程序,main函数中都有一个QCoreApplication/QGuiApplication/QApplication,并在末尾调用 exec。Application中的这个EventLoop,我们称作“主事件循环”,所有的事件分发、事件处理都从这里开始。Application还提供了sendEvent和poseEvent两个函数,分别用来发送事件。sendEvent发出的事件会立即被处理,也就是“同步”执行。postEvent发送的事件会被加入事件队列,在下一轮事件循环时才处理,也就是“异步”执行。
函数阻塞
我们常常使用Qt来编写UI界面,这样确实很方便,但是Qt的事件循环机制在这里会出现一些问题。举两个例子:
比如说:假设我们有一个鼠标点击事件,事件循环会分发出这个鼠标点击事件,调用特定的鼠标事件处理函数,但是这个信号却做了很多耗时的事情,于是便堵塞着、等待着事件处理函数返回,这是堵塞了时间循环,它意味着没有消息被分发了,再次有事件或消息时无法被及时分发处理,直到我们从槽函数返回了,然后才能继续处理挂起的消息。
再比如说:我们有时候又需要做一些复杂的计算,这段计算程序就在我们的UI界面的事件循环中,这些计算的耗时甚至达到了几秒钟,在没有计算完成之前,函数不会退出(相当于阻塞),事件循环得不到及时处理,就会发生UI卡住的现象。
多线程使用
以上两种情况,在消息循环被卡住的情况下,widgets将不能更新它们自身,不可能有更多的互动,timers将不会被激发,网络通讯将缓慢下来,或者停止。进一步的说,许多窗口管理器将检测到你的应用程序不在处理事件了, 然后告诉用户你的程序没有响应。这就是为什么快速的对事件响应并且即时返回到事件循环是多么的重要。
对于上述两种情况,假如我们有一个很长的任务去运行但是又不希望堵塞这个消息循环,该怎么做呢?可行的方法如下:
将这个任务移到另一个线程中,
我们也能手动强制事件循环去运行,这个方法是通过在堵塞的任务函数中调用QCoreApplication::processEvent()来实现,QCoreApplication::processEvent()将处理所有在消息队列中的消息并返回给调用者。
另一个可选的选项是我们能够强制重入事件循环的对象,就是QEventLoop类。通过调用QEventLoop::exec()我们将重入事件循环,然后我们能将槽函数QVentLoop::quit()连接到信号上去使它退出。
其中最常用的是创建子线程的办法
相关文章
- qt中的进程优先级及应用内存大小设置方法,VS和Qt工程中申请超过2G的内存的方法
- Qt对话框的事件循环分析(子线程中不能创建UI窗体分析2)
- QT-多线程重要概念及与界面之间交互总结(混淆点分析:c#中可以在子线程中创建ui控件,qt中不能在子线程中创建ui控件)
- Qt对话框的事件循环分析(子线程中不能创建UI窗体分析)
- QT信号和槽
- 解决qt程序运行时的cannot create Qt for Embedded Linux data directory: /tmp/qtembedded-0出错情形
- 【QT】Qt::UserRole的作用
- 【QT】Qt creator连接MySQL数据库 - 增删改查
- 【QT】Qt多版本交叉编译所遇到的问题以及如何解决(重在思路过程)
- therecipe / qt Windows版本安装
- QT工具——qt for vs
- Qt开源作品44-超级曲线图表
- Qt编写安防视频监控系统45-图文报表
- Qt编写的项目作品28-视频监控显示安卓版
- Qt开发经验小技巧81-90
- Qt编写数据可视化大屏界面电子看板10-改造QCustomPlot
- Qt主界面卡死的解决方案-一些具体实现方式(五种方法)
- Qt 事件系统浅析 (用 Windows API 描述,分析了QCoreApplication::exec()和QEventLoop::exec的源码)(比起新号槽,事件机制是更高级的抽象,拥有更多特性,比如 accept/ignore,filter,还是实现状态机等高级 API 的基础)
- QT in VS 多语言实现(中英文切换,每个步骤都有截图,只有UTF8才能让Qt语言家正确读取。先qApp->removeTranslator,然后installTranslator,每个类都要写上槽函数RetranslateUI)
- Qt状态机框架(状态机就开始异步的运行了,也就是说,它成为了我们应用程序事件循环的一部分了)
- Qt 学习之路 2(19):事件的接受与忽略(当重写事件回调函数时,时刻注意是否需要通过调用父类的同名函数来确保原有实现仍能进行!有好几个例子。为什么要这么做?而不是自己去手动调用这两个函数呢?因为我们无法确认父类中的这个处理函数有没有额外的操作)
- VS2010使用静态编译的qt库(Qt 5)
- Qt 为搜索结果增加右键菜单
- 【正点原子Linux连载】第八章 文本读写摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2