首页 两轮车 三轮车 汽车 头条 报价 推荐 资讯 焦点 品牌 技术
首页 >  头条 > 

使用QEventLoop将异步操作变成同步操作

2023-05-13 17:19:30 来源:QT教程

异步调用举例

我们来看一个例子,我们向服务器请求服务器时间,异步的方式,我们的写法是这样的:

void Helper::getServerTimeAsync(){auto networkManager = new QNetworkAccessManager;connect(networkManager, &QNetworkAccessManager::finished, [=](QNetworkReply* reply) {networkManager->deleteLater();emit serverTime(reply->rawHeader(\"time\").toLongLong());});networkManager->get(QNetworkRequest(QUrl(\"https://10.10.10.1/time\")));}

在上述代码中,我们通过连接QNetworkAccessManager::finished信号来在未来某个时候发出finished信号时处理回复数据,然后将得到的时间以信号的方式发出去。

调用者在使用这个接口时,那就是下面这样:


(资料图)

auto helper = new Helper;connent(helper, &Helper::serverTime, [](time_t time) {qDebug() << time;});helper.getServerTimeAsync();

相当于调用getServerTimeAsync只是发一个获取时间的请求,这个时候并不能立即得到时间,必须在未来某个时候Helper::serverTime信号触发时才能得到时间。

改成同步调用

现在,我们通过QEventLoop来改成同步调用:

time_t Helper::getServerTimeSync(){QNetworkAccessManager networkManager;QEventLoop eventLoop;QTimer timer;connect(&timer, &QTimer::timeout, [&eventLoop] { eventLoop.quit(); });connect(&networkManager, &QNetworkAccessManager::finished, [&eventLoop](QNetworkReply* reply) {eventLoop.quit();});auto reply = networkManager.get(QNetworkRequest(QUrl(\"https://10.10.10.1/time\")));timer.start(3000);eventLoop.exec();reply->deleteLater();if (reply->error() != QNetworkReply::NoError)return 0;return reply->rawHeader(\"time\").toLongLong();}

如上代码,创建定时器用于超时处理,超时时直接退出事件循环;QNetworkAccessManager::finished触发时也退出事件循环;最后使用QEventLoop来开启事件循环阻塞当前函数(由于是阻塞调用,那networkManager不需要new,直接局部变量即可);当超时时间到或者finished信号触发时事件循环退出,我们再去从reply里解析时间,最后返回。

可能看上面代码,实现变复杂了好多,但是接口使用起来就简单很多:

qDebug() << helper.getServerTimeSync();

1.

总结

很多异步的操作,比如上面的QNetworkAccessManager的post、get,或者使用QProcess创建子进程处理任务的情况,都可以改成同步调用,但是要注意的时,改成同步调用后,在调用返回之前,函数是被阻塞掉的,修改之前就要考虑阻塞的话会不会影响业务逻辑。

【领 QT开发教程 学习资料, 点击下方链接莬费领取↓↓ ,先码住不迷路~】

点击这里:

关键词:

下一篇:最后一页
上一篇:推出小微网格星级创建,嘉定区探索党建引领网格治理新路径

相关新闻