2015-04-04 22 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

你怎麼想中斷事件循環在第二種情況下側?首先是好的,但你也應該處理錯誤。 – 2015-04-04 17:52:59

+0

是的,那就是我正在努力,所以我改變了它。我只是不確定我是否正確思考,所以我問 – 2015-04-04 18:04:47

+1

一般來說你不應該使用 - QApplication已經爲主線程設置了一個事件循環,而QThread爲後臺線程設置了一個事件循環。 – MrEricSir 2015-04-04 18:25:57

回答

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

,你也需要以某種方式處理情況Manager不發出SIGNAL(finished(QNetworkReply*))可言。

1

我同意@ Mher-Didaryan--事件循環從第二代碼片段中的代碼行loop.exec();開始 - 將永遠不會退出。這是因爲連接()之間SIGNAL和SLOT正在完成不同的事件循環比通過EventLoop loop;指示的事件循環。

在第一個代碼片段的情況下,邏輯取決於與一個&相關的finished(QNetworkReply*)信號發送到兩個不同的事件循環。但它很可能是manager->get(request) ;已發出的finished(QNetworkReply*)信號後

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

可能執行。也許它可能發生在涉及非常小的文件或響應的GET類型的HTTP操作中。在這種情況下,由第一個代碼片段中的loop.exec();開始的事件循環也不會退出。我猜這就是@ Mher-Didaryan也在回答他的問題。

也許你可以使用,將處理好以下幾個負面執行場景太

  1. 定時進行GET請求的(比如由於網絡連接問題)以下QEventLoop邏輯從服務器
  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;