• 154阅读
  • 9回复

[提问]事件循环是什么? [复制链接]

上一主题 下一主题
离线介农酥
 

只看楼主 倒序阅读 楼主  发表于: 08-13
QT的事件循环是什么,一直不是很理解。
比如QEventLoop的本地循环,线程exec(),qApp的exec()等。
返回到事件循环又是什么意思?


20190816增加
exec()后面的代码无法执行,前面的代码造成的任何结果都可以运行,比如connect,计时器,事件对吧,那其他线程给他发信号他会处理吗,应该会,对吧。那这个QEventLoop本地循环呢,这个本地循环应该只响应本地的(从线程开始到loop.exec())的事件吧,那线程的exec()只响应线程的内的事件吗,这个似乎不对,应该其他线程可以给它发信号,主线程循环是否就是响应主线程及其子线程所有的事件,这样理解对吗?

离线笑颜

只看该作者 1楼 发表于: 08-13
Qt的事件循环是什么? 可以这样给你解释。
假设我们写个简单的main函数,如果没有任何阻塞,那么这个main函数很快就结束了,那么一般情况下进程就结束了。
事件循环就相当于在main函数里面写了个while(1);让main函数一直不结束,进程就一直不会退出。
然后,我们知道对于界面程序来说,用户在界面上做任何事情都是随机的,比如点击一下鼠标,按下一个按键。那么要怎么来处理这些随机的操作呢? 那就是事件循环。
其实事件循环可以想象成一个一个的回调函数封装,根据不同的事件类型进入事先写好的事件处理函数,也就是回调函数。

所以,最终解释事件循环就是,一个容器,装了一些用户触发的事件,然后在while(1)循环里面一直遍历这个容器(当然,触发的时候装进去,处理之后删掉),有事件就调用事件的处理函数,没有就处理一些其他的事情(当然,你什么也不做也可以),最后你想应用程序退出,当然就结束这个while循环了。
离线fsu0413

只看该作者 2楼 发表于: 08-13
事件循环不是Qt的概念,而是应用程序的概念。
本质来说,就是用来接收事件并调用事件响应函数的循环。
离线ustone

只看该作者 3楼 发表于: 08-14
学过Windows程序设计第一章就知道了。
离线介农酥

只看该作者 4楼 发表于: 08-16
回 笑颜 的帖子
笑颜:Qt的事件循环是什么? 可以这样给你解释。
假设我们写个简单的main函数,如果没有任何阻塞,那么这个main函数很快就结束了,那么一般情况下进程就结束了。
事件循环就相当于在main函数里面写了个while(1);让main函数一直不结束,进程就一直不会退出。
然后,我们知道对于界面程序 .. (2019-08-13 20:43) 

exec()后面的代码无法执行,前面的代码造成的任何结果都可以运行,比如connect,计时器,事件对吧,那其他线程给他发信号他会处理吗,应该会,对吧。那这个QEventLoop本地循环呢,这个本地循环应该只响应本地的(从线程开始到loop.exec())的事件吧,那线程的exec()只响应线程的内的事件吗,这个似乎不对,应该其他线程可以给它发信号,主线程循环是否就是响应主线程及其子线程所有的事件,这样理解对吗?
离线笑颜

只看该作者 5楼 发表于: 08-16
回 介农酥 的帖子
介农酥:exec()后面的代码无法执行,前面的代码造成的任何结果都可以运行,比如connect,计时器,事件对吧,那其他线程给他发信号他会处理吗,应该会,对吧。那这个QEventLoop本地循环呢,这个本地循环应该只响应本地的(从线程开始到loop.exec())的事件吧,那线程的exec()只响应线程的 .. (2019-08-16 13:08) 

在这里如果我们只考虑Qt的事件循环,那么可以继续描述。

事件循环相当于是一个阻塞的操作,所以不管在哪个线程里面启动起来就没办法再执行后面的指令。
Qt的事件循环就是用QEventLoop来做的,如果你在事件循环里面再嵌套一个事件循环,肯定也是不能再执行后面的指令,但是你嵌套的那个事件循环是可以处理所有的事件的(包括外层的循环里的事件,exec有个参数指定处理事件类型)

然后不同的线程里面都可以启动一个事件循环,另外跨线程的信号传递,一般情况下都是封装成一个回调函数的事件,派发到指定的线程事件循环里面执行,所以是线程安全的。

每个线程里面的事件循环都是独立的,但是同一个线程里面的多个事件循环应该是共享同一个事件队列的。
离线onlyone

只看该作者 6楼 发表于: 08-16
与windows 程序设计里面的事件循环是类似的概念。
虽然我没有看过qt源码,但是如果你用sdk开发过windows程序,需要自己写一个windows的事件循环机制。进入事件循环后,实际上是在等待用户的操作。

比如用户点击退出,会触发windows退出事件的操作。
点击按钮,会触发按钮点击事件等等。



QT中每个线程都有自己的事件循环。

所以“主线程循环是否就是响应主线程及其子线程所有的事件,这样理解对吗?” 这个是不完全对的。
主线程响应自己的事件。
子线程也有自己的事件循环。

垮线程发信号消息,就是把发送的线程,把消息丢到对方线程的消息队列上去。接收线程的事件循环会从自己的消息队列上取消息,进而去执行。

如果线程阻塞,那么无法进入事件循环,也就无法响应一切事件。如果主线程被阻塞,给人感觉就是界面卡死不响应。

如果你有过windows sdk 编程,有些地方知识都是类似的,虽然不全部完全相同。

离线介农酥

只看该作者 7楼 发表于: 08-17
回 笑颜 的帖子
笑颜:在这里如果我们只考虑Qt的事件循环,那么可以继续描述。
事件循环相当于是一个阻塞的操作,所以不管在哪个线程里面启动起来就没办法再执行后面的指令。
Qt的事件循环就是用QEventLoop来做的,如果你在事件循环里面再嵌套一个事件循环,肯定也是不能再执行后面的指令,但是你嵌套 .. (2019-08-16 15:54) 

离线介农酥

只看该作者 8楼 发表于: 08-17
回 onlyone 的帖子
onlyone:与windows 程序设计里面的事件循环是类似的概念。
虽然我没有看过qt源码,但是如果你用sdk开发过windows程序,需要自己写一个windows的事件循环机制。进入事件循环后,实际上是在等待用户的操作。
比如用户点击退出,会触发windows退出事件的操作。
点击按钮,会触发按钮点击事件 .. (2019-08-16 16:03) 

离线fsu0413

只看该作者 9楼 发表于: 08-17
没有QEventLoop的话,系统事件怎么处理?
如果把main函数中的exec调用换成for(;;) 的死循环,程序还是一样不退出,但是你的界面八成是出不来的,即使出来也不会好用,因为没有处理事件相关的代码。

QEventLoop并不只是处理系统事件,它还处理队列(注意不是跨线程)的信号槽调用。
它可能还处理其他的内容,我没有具体研究过,有兴趣的话可以研究下。
快速回复
限100 字节
 
上一个 下一个