2015-04-04 2 views
7

У меня есть сомнения, как использовать QEventLoop. У меня есть 2 части кода, оба они работают для меня (загрузите веб-ресурс).Правильное использование QEventLoop

Первый один:

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(), как в первом? Я нашел второе решение где-то, но мне это не показалось правильным, поэтому я изменил его на первую часть кода.

+0

Как вы хотите, чтобы прервать цикл событий во втором случае? Сначала все в порядке, но вы также должны обрабатывать ошибки. –

+0

Да, это то, что я беспокоился, поэтому я изменил его. Я просто не был уверен, правильно ли я думал, поэтому я спросил –

+1

В общем, вы не должны использовать ни один из них - QApplication уже устанавливает цикл событий для основного потока, а QThread устанавливает цикл событий для фоновых потоков. – MrEricSir

ответ

1

В вашем втором примере цикл событий никогда не будет прекращен, с другой стороны, в первом примере цикл прекратится, когда выйдет 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*)) вообще.

1

Я согласен с @ Mher-Didaryan - что цикл событий начинается следующей строкой кода loop.exec(); во втором фрагменте кода - никогда не будет завершен. Это связано с тем, что connect() между SIGNAL и SLOT выполняется для другого цикла событий, чем контур события, указанный через EventLoop loop;.

В случае фрагмента 1-го кода логика зависит от сигнала finished(QNetworkReply*), связанного с одним & тем же запросом GET, испускаемым на два разных цикла событий. Но вполне возможно, что

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

вполне может выполнить после manager->get(request) ; эмитировал в finished(QNetworkReply*) сигнал. Возможно, это может произойти для HTTP-операции GET, содержащей очень маленький файл или ответ. В таком случае цикл событий, начатый loop.exec(); в первом фрагменте кода, также не будет завершен. Я предполагаю, что это то, о чем также просит Мгер-Дидарьян в своем ответе.

Может быть, вы можете использовать ниже QEventLoop логику, которая будет обрабатывать следующие негативные сценарии выполнения слишком

  1. Timing из запроса GET (скажем из-за проблем с подключением к сети) типа
  2. Ошибка ответа от сервера сторона сети

    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; 
    

 Смежные вопросы

  • Нет связанных вопросов^_^