1. 程式人生 > >利用QEventLoop實現同步等待信號槽返回結果

利用QEventLoop實現同步等待信號槽返回結果

有一個 str ID 主程 col 一個 例子 就是 pid

在QT中想要實現一個簡單的函數:給定一個網頁地址(http://www.hao123.com),等待返回網頁的html內容。

當然我想到可利用QNetWork相關的類:QNetworkAccessManager、QNetworkRequest、QNetworkReply三個類;進一步深入發現,網絡訪問一般是異步的,因此Qt中reply的結果是利用信號/槽機制來進行通知和處理的,這仍然是異步的,也就是說不能立即取得reply結果,而只能在槽函數中來處理reply結果。我也想到用lambda函數實現槽函數,似乎能立即取得結果,但可惜的是lambda函數仍然是異步調用的。

所以想簡單的一個函數實現以上功能不現實。我用一個類來實現該功能。

頭文件:webspider.h

 1 #include "QtNetwork\QNetworkAccessManager"
 2 class WebSpider:public QObject
 3 {
 4     Q_OBJECT    
 5 public:
 6     WebSpider();
 7     ~WebSpider();
 8 
 9     QString getHtml(QString urlStr);
10 
11 public slots:
12     void requestFinished(QNetworkReply *reply);
13 private: 14 QNetworkAccessManager* _netManager; 15 QNetworkRequest* _netRequest; 16 17 QByteArray _replyResult; 18 };

實現文件:webspider.cpp

 1 #include "WebSpider.h"
 2 #include "QEventLoop"
 3 #include "QtNetwork\QNetworkAccessManager"
 4 #include "QtNetwork\QNetworkReply
" 5 #include "QObject" 6 7 8 9 WebSpider::WebSpider() 10 :QObject() 11 { 12 _netManager = new QNetworkAccessManager(); 13 14 } 15 16 17 WebSpider::~WebSpider() 18 { 19 delete _netManager; 20 } 21 22 QString WebSpider::getHtml(QString urlStr) 23 { 24 _netRequest = new QNetworkRequest(QUrl(urlStr)); 25 _netManager->get(*_netRequest); 26 27 QEventLoop* el = new QEventLoop(); 28 29 connect(_netManager, &QNetworkAccessManager::finished, el, &QEventLoop::quit); //網絡訪問結束時,結束事件循環 30 connect(_netManager, &QNetworkAccessManager::finished, this, &WebSpider::requestFinished); //網絡訪問結束時,處理返回結果 31 el->exec(); //開始事件循環,等待網絡訪問結束 32 //事件循環結束後,requestFinished槽中已獲取網絡訪問結果,保存於_replyResult中 33 return QString(_replyResult); //返回結果 34 } 35 36 void WebSpider::requestFinished(QNetworkReply *reply) 37 { 38 _replyResult=reply->readAll(); 39 }

在程序中只需要簡單二行代碼就可取得結果

1 WebSpider ws;
2 QString htmlStr=ws.getHtml("http://www.hao123.com");

就象一個函數一樣,結果立即就獲得了,沒有異步訪問的感覺了,呵呵。任務達成。
WebSpider中實際上是異步的,但利用QEventLoop等待異步調用後,再返回結果的,也就是說,有一個等待的過程。這裏我們沒有考慮網絡異常的可能,具體應用中可進一步完善。

在QT中異步無處不在,這個小例子有助於我們實現一些簡單的小功能,將異步的代碼集中包裝,在主程序中代碼將顯示出簡單直接。

利用QEventLoop實現同步等待信號槽返回結果