Qt中的事件循环
我们先看一个程序,
1 | int main(int argc, char *argv[]) |
很熟悉对不对,每一个初学Qt的同学都见过。
QApplication
是个啥?a.exec()
在干嘛?
事件
和之前GUI框架一样,Qt也是事件驱动的。
这里的“事件”可能来自应用程序自己,也可能来自外部。
比如用户交互:鼠标单击或按键,或与其他线程通信,也可能来自操作系统或其他进程的消息。
Qt把这些事件封装成了QEvent
, 比如QKeyEvent
, QMouseEvent
. 当然,你也可以自定义自己的事件。
事件循环
事件循环做些啥?它看起来像下面这样:
1 | while (!interrupted) { |
Qt中对应的事件循环的类是QEventLoop
.
1 | class QEventLoop : public QObject { |
文章开头的a.exec()
实际上是开启了一个事件循环。
1 | int QCoreApplication::exec() |
所有的事件分发、事件处理都从a.exec()
开始。
而当我们调用qApp->quit()
退出应用程序时,实际上也退出了事件循环。
1 | void QCoreApplication::exit(int returnCode) |
程序未响应?
程序在什么情况下会出现未响应的情况?
当我们在主线程中进行耗时操作,阻塞了事件循环,无法响应其他事件时,就会出现类似上面的假死现象。
如何避免?
一般地,我们会在另外的线程中处理耗时的操作。
那除了另开线程,还有没有其他方式?
processEvents()
有,就是强制调用processEvents()
1 | for (auto i : list) { |
虽然这也能避免程序假死,但通常我们不建议这么做。因为它很难确定应多久调用一次processEvents()
来最大化可用性和性能,这取决于硬件。
另起事件循环
还有,我们可以通过另起一个事件循环来避免程序假死。我们通常在访问网络资源时这么做。
1 | QNetworkReply *reply = manager->post(request, body); |
通过另起事件循环,我们把本身异步的操作变成了同步,在实际编码过程中,这很有效。