• 利用QEventLoop实现同步等待信号槽返回结果


    在QT中想要实现一个简单的函数:给定一个网页地址(http://www.hao123.com),等待返回网页的html内容。

    当然我想到可利用QNetWork相关的类:QNetworkAccessManager、QNetworkRequest、QNetworkReply三个类;进一步深入发现,网络访问一般是异步的,因此Qt中reply的结果是利用信号/槽机制来进行通知和处理的,这仍然是异步的,也就是说不能立即取得reply结果,而只能在槽函数中来处理reply结果。我也想到用lambda函数实现槽函数,似乎能立即取得结果,但可惜的是lambda函数仍然是异步调用的。

    我用一个类来实现该功能。

    头文件:webspider.h

     1 #include "QtNetworkQNetworkAccessManager"
     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 "QtNetworkQNetworkAccessManager"
     4 #include "QtNetworkQNetworkReply"
     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中异步无处不在,这个小例子有助于我们实现一些简单的小功能,将异步的代码集中包装,在主程序中代码将显示出简单直接。

    进一步,如果槽函数可直接写成lambda函数,则所有过程可简化为一个函数的形式。

  • 相关阅读:
    学习日报
    学习日报
    学习日报
    学习日报
    《人月神话》读后感(第一二章)
    线程
    for each
    类的访问属性
    异常
    输入输出流
  • 原文地址:https://www.cnblogs.com/jiaping/p/8997815.html
Copyright © 2020-2023  润新知