Qt 事件循环与其他语言/框架中的抽象相同吗?

问题描述 投票:0回答:1

作为我的问题的一个例子,当我们只想从 HTTP 服务器获取一些数据时,我想分享一个经常推荐的 API 示例:

QNetworkRequest req;
QNetworkAccessManager mgr;
QNetworkReply *reply;
QEventLoop eventLoop;
QString buffer;
QString url;

QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
url = "https://api.test.com/text1";
req.setUrl(QUrl(url);
reply = mgr.get(req);
eventLoop.exec();
buffer = reply->readAll();
delete reply;

它确实有效,但从网络上的信息来看,它被认为是一个错误的习惯,应该避免。

之前,我曾经想知道为什么有些人尝试应用的 while 循环示例不起作用,据我所知,我们现在阻止了所有内容,堆栈和事件(因为需要首先提供堆栈,然后是事件队列?)不起作用:

url = "https://api.test.com/text1";
req.setUrl(QUrl(url);
reply = mgr.get(req);
while (!reply->isFinished()){}
buffer = reply->readAll();
delete reply;

然后我们找到了另一个可行且安全的解决方案:

url = "https://api.test.com/text1";
req.setUrl(QUrl(url);
reply = mgr.get(req);
while (!reply->isFinished()){
 QApplication::processEvents();
}
buffer = reply->readAll();
delete reply;

上面的示例工作正常,所以我宁愿继续使用它,但是当然可以选择使用信号和槽来做到这一点:

void binConCl::replyFinished(QNetworkReply *reply){
 buffer = reply->readAll();
 delete reply;
}

QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
url = "https://api.test.com/text1";
req.setUrl(QUrl(url);
reply = mgr.get(req);

当然,应该将缓冲区和回复声明为这些函数所在类的私有变量,例如在头文件中。

这个示例为我的目的增加了更多工作,因为我正在调用函数,包括所有连接、请求发送等,然后我将缓冲区解析为 JSON 对象,并且需要返回它,所以我必须从

replyFinished
发送另一个信号回到GUI,但我认为这是Qt的方式和正确的方式。你觉得怎么样?

我了解事件循环如何运作吗?事件循环也是一种 while 循环,检查所有调用的内容、信号等。

因此,当我们像第一个示例中那样使用内部 QEventLoop 时,我们是否在同一线程中调用新线程或某种新堆栈/队列(有可能吗?)?。

我在JavaScript会议上观看了这个视频,它的解释很容易理解,这个片段大约1-2分钟,但我仍然有疑问。

c++ qt event-handling event-loop
1个回答
0
投票

一个事件循环有 3 个作业。

  1. 从操作系统获取消息。
  2. 将这些消息分派到适当的处理程序(SLOTS)。
  3. 睡觉,直到有更多工作可做。

QEventLoop 允许您创建一个本地事件循环,它将调用

QApplication
事件循环来完成所有 3 个任务,但是嵌套循环会产生一系列问题,您应该避免嵌套事件循环。

一个简单的实现,你只调用

QApplication::processEvents();
不会执行睡眠部分,并且如果没有睡眠,你的 CPU 将被固定在 100% 并且浪费大量的电量而不做任何事,文档不鼓励直接在 a 中调用
processEvents
循环

按照文档中建议的正确方法执行执行时在 SLOT 中处理结果的解决方案,就像您一样。

  1. 避免本地事件循环
  2. 让你的CPU进入睡眠状态

如果您的函数必须维护状态并且不能拆分为两个函数,那么您应该将其放在QThread上,并在那里运行

QEventLoop
,您不必担心嵌套循环,因为该循环只会等待对于仅与该线程相关的一两个事件,但您应该限制您创建的线程数量。

© www.soinside.com 2019 - 2024. All rights reserved.