我想知道我应该如何使用QEventLoop
.我有 2 段代码,它们都对我有用(下载网络资源(。
第一个:
QNetworkAccessManager *manager = new QNetworkAccessManager( this );
QNetworkRequest request;
request.setUrl(QUrl(url));
request.setRawHeader("User-Agent", "Mozilla Firefox");
connect(manager, SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
manager->get( request ) ;
QEventLoop loop;
connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
loop.exec();
第二个:
QNetworkAccessManager *manager = new QNetworkAccessManager( this );
QNetworkRequest request;
request.setUrl(QUrl(url));
request.setRawHeader("User-Agent", "Mozilla Firefox");
manager->get( request ) ;
QEventLoop loop;
connect(manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
loop.exec();
我想知道的是我应该使用哪一个。我的意思是,在发出信号后,事件循环是否会在第二个事件循环中退出?还是我必须像第一个那样打电话给quit()
?我在某处找到了第二个解决方案,但对我来说似乎不合适,所以我将其修改为第一段代码。
我同意 @Mher-Didaryan 的观点——事件循环由第二个代码片段中的代码行loop.exec();
启动——永远不会退出。这是因为 SIGNAL 和 SLOT 之间的 connect(( 是为与通过 EventLoop loop;
指示的事件循环不同的事件循环完成的
在第一个代码片段的情况下,逻辑取决于与发送到两个不同事件循环的一个和相同的GET请求相关联的finished(QNetworkReply*)
信号。但很有可能
connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
很可能在manager->get( request ) ;
发出finished(QNetworkReply*)
信号后执行。对于涉及非常小的文件或响应的GET类型HTTP操作,可能会发生这种情况。在这种情况下,由第一个代码段中的loop.exec();
启动的事件循环也不会退出。我想这也是@Mher-迪达良在他的回答中询问的。
也许您可以使用下面的QEventLoop逻辑来处理以下负面执行场景
- GET请求超时(例如由于网络连接问题(
来自网络服务器端的错误类型响应
QNetworkAccessManager *manager = new QNetworkAccessManager(this); QNetworkRequest request; QEventLoop loop; QTimer getTimer; // let's use a 10 second period for timing out the GET opn request.setUrl(QUrl(url)); request.setRawHeader("User-Agent", "Mozilla Firefox"); // connect the timeout() signal of getTimer object to quit() slot of event loop QTimer::connect(&getTimer,SIGNAL(timeout()),&loop, SLOT(quit())); QObject::connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit())); QNetworkReply *resp = manager->get( request ); getTimer.start(10000); // 10000 milliSeconds wait period for get() method to work properly loop.exec(); if(NULL == resp) { // Error. we probably timed out i.e SIGNAL(finished()) did not happen // this handles above indicated case (1) return -1; // or return some timeout related error value } else if( QNetworkReply::NoError != resp->error() ) { // Error - SIGNAL(finished()) was raised but get() opn failed & returned with error // Refer http://doc.qt.io/qt-4.8/qnetworkreply.html#NetworkError-enum // This section of code handles above indicated case (2) } else { // get() operation was Successful !. // read the response available in the 'resp' variable as a QString & parse it. // Obtain the necessary result and etc. } delete resp; delete manager;
在第二个示例中,事件循环永远不会退出,另一方面,在第一个示例中,当finished(QNetworkReply*)
发出时,循环将退出。但是manager->get( request );
如果在连接环路退出之前导致信号finished(QNetworkReply*)
发出怎么办?
QNetworkAccessManager *manager = new QNetworkAccessManager( this );
QNetworkRequest request;
QEventLoop loop;
request.setUrl(QUrl(url));
request.setRawHeader("User-Agent", "Mozilla Firefox");
connect(manager, SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
manager->get( request ) ;
loop.exec();
而且您还需要以某种方式处理管理器根本不发出SIGNAL(finished(QNetworkReply*))
的情况。