2015-04-04 12 views
7

Ich habe Zweifel, wie sollte ich QEventLoop verwenden. Ich habe 2 Stück Code, beide funktionieren für mich (Web-Ressource herunterladen).QEventLoop richtige Verwendung

erste:

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

Zweite ein:

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

Was ich wissen will, ist, was soll ich verwenden. Ich meine, endet die Ereignisschleife in der zweiten, nachdem das Signal ausgelöst wurde? Oder muss ich quit() wie in der ersten anrufen? Ich fand die zweite Lösung irgendwo, aber es schien mir nicht passend, also habe ich es in das erste Stück Code geändert.

+0

Wie wollen Sie Ereignisschleife in zweiten Fall zu unterbrechen? Zuerst ist OK, aber Sie sollten auch Fehler behandeln. –

+0

Ja, das war es, worüber ich mir Sorgen machte, also habe ich es geändert. Ich war einfach nicht sicher, ob ich richtig dachte, also fragte ich –

+1

Im Allgemeinen sollten Sie auch nicht verwenden - QApplication richtet bereits eine Ereignisschleife für den Hauptthread ein, und QThread richtet eine Ereignisschleife für Hintergrundthreads ein. – MrEricSir

Antwort

1

In Ihrem zweiten Beispiel wird die Ereignisschleife nie beendet, auf der anderen Seite wird die Schleife in Ihrem ersten Beispiel beendet, wenn ausstrahlt. Aber was passiert, wenn manager->get(request); das Signal finished(QNetworkReply*) verursacht, das ausgegeben wird, bevor Sie loops quit damit verbinden?

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

Und auch Sie müssen irgendwie Situation zu handhaben, wo Manager nicht SIGNAL(finished(QNetworkReply*)) überhaupt emittiert.

1

Ich stimme mit @ Mher-Didaryan überein - dass die Ereignisschleife mit der folgenden Codezeile loop.exec(); im zweiten Code-Snippet gestartet wird - wird nie beendet. Dies liegt daran, dass connect() zwischen SIGNAL und SLOT für eine andere Ereignisschleife als die durch EventLoop loop; angezeigte Ereignisschleife ausgeführt wird.

Im Fall des ersten Codeausschnitts hängt die Logik vom Signal finished(QNetworkReply*) ab, das mit einer & gleichen GET-Anforderung verbunden ist, die an zwei verschiedene Ereignisschleifen ausgegeben wird. Aber es ist durchaus möglich, dass

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

kann auch ausgeführt werden, nachdem die manager->get(request) ; das finished(QNetworkReply*) Signal ausgesendet hat. Vielleicht kann es bei einer HTTP-Operation vom GET-Typ vorkommen, die eine sehr kleine Datei oder Antwort enthält. In einem solchen Szenario wird die Ereignisschleife, die durch das loop.exec(); im ersten Code-Snippet gestartet wurde, ebenfalls nicht beendet. Ich denke, das ist was @ Mher-Didaryan in seiner Antwort auch abfragt.

Vielleicht können Sie die unten QEventLoop Logik verwenden, die die folgenden negativen Ausführungsszenarien zu

  1. -Timing aus der GET-Anforderung (zB aufgrund von Netzwerkkonnektivitätsproblemen)
  2. Fehlertyp Antwort vom Server behandeln würden Seite Netzwerk

    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;