我们来看一个例子,我们向服务器请求服务器时间,异步的方式,我们的写法是这样的:
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开发教程 学习资料, 点击下方链接莬费领取↓↓ ,先码住不迷路~】
点击这里:
标签:
Copyright © 2015-2022 南极经营网版权所有 备案号:粤ICP备2022077823号-13 联系邮箱: 317 493 128@qq.com