QEventLoop的正确用法 [英] QEventLoop proper usage
问题描述
我怀疑我应该如何使用QEventLoop
.我有2段代码,它们都对我有用(下载Web资源).
第一个:
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;
指示的事件循环不同的事件循环进行的.
在第一个代码段的情况下,逻辑取决于与一个& amp;关联的finished(QNetworkReply*)
信号.相同的GET请求被发送到两个不同的事件循环.
connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
在manager->get( request ) ;
发出finished(QNetworkReply*)
信号之后,
可以很好地执行.对于包含很小文件或响应的GET类型HTTP操作,可能会发生这种情况.在这种情况下,由第一个代码段中的loop.exec();
开始的事件循环也不会退出.我想这就是@ Mher-Didaryan在他的答案中也在查询的内容.
也许您可以使用下面的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;
I have doubts how should I use QEventLoop
. I have 2 pieces of code, both of them work for me (get web resource downloaded).
First one:
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();
Second one:
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();
What I want to know is which one should I use. I mean, does the event loop quit in the second one after signal is emmited? Or do I have to call quit()
like in the first one? I found the second solution somewhere but it didn't seem proper to me so I modified it into first piece of code.
I agree with @Mher-Didaryan - that the event loop started by following line of code loop.exec();
in the 2nd code snippet - will never exit. This is because the connect() between the SIGNAL and SLOT is being done for a different event loop than the event loop indicated through EventLoop loop;
.
In the case of the 1st code snippet, the logic depends on the finished(QNetworkReply*)
signal associated with one & same GET request being emitted to two different event loops. But it is quite possible that
connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
may well execute after the manager->get( request ) ;
has emitted the finished(QNetworkReply*)
signal. Maybe it can happen for a GET type HTTP operation involving a very small file or response. In such a scenario the event loop started out by the loop.exec();
in the 1st code snippet will also not exit. I guess this is what @Mher-Didaryan is also querying in his answer.
Maybe you can use the below QEventLoop logic that would handle the following negative execution scenarios too
- Timing out of the GET request (say due to network connectivity issues)
Error type response from server side of network
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;
这篇关于QEventLoop的正确用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!