Proper Use of QEventLoop

I have doubts about how to use QEventLoop . I have 2 pieces of code, both of them work for me (download the web resource).

First:

 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:

 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(); 

I want to know what I should use. I mean, does the event loop end in the second after the signal comes out? Or do I need to call quit() , as in the first? I found the second solution somewhere, but it didn't seem right to me, so I changed it to the first part of the code.

+7
qt qtnetwork qeventloop
source share
2 answers

In your second example, the event loop will never end; on the other hand, in the first example, the loop will stop when finished(QNetworkReply*) emits. But what if manager->get( request ); cause the finished(QNetworkReply*) signal finished(QNetworkReply*) , which must be emitted before you connect the loop to it?

 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(); 

And also you need to somehow cope with a situation where the manager does not allocate SIGNAL(finished(QNetworkReply*)) .

+1
source share

I agree with @ Mher-Didaryan - that the event loop started by the following line of code loop.exec(); in the second code snippet will never exit. This is because the connect () between SIGNAL and SLOT is executed for a different event loop than the event EventLoop loop; designated through the EventLoop loop; .

In the case of the 1st code fragment, the logic depends on the finished(QNetworkReply*) signal finished(QNetworkReply*) , due to the fact that the same GET request is emitted on two different events. But it is entirely possible that

  connect(manager, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit())); 

may well execute after manager->get( request ) ; emitted a finished(QNetworkReply*) signal finished(QNetworkReply*) . Perhaps this could happen for the HTTP GET operation containing a very small file or response. In this case, the event loop started by loop.exec(); in the 1st code fragment will also not be completed. I guess this is what Mher-Didaryan also asks for in his answer.

Perhaps you can use the QEventLoop logic below, which will also handle the following negative execution scripts.

  • GET request deadlines (e.g. due to network connectivity issues)
  • Network server side error type response

     QNetworkAccessManager *manager = new QNetworkAccessManager(this); QNetworkRequest request; QEventLoop loop; QTimer getTimer; // let 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 ie 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; 
+1
source share

All Articles