QEventLoop的正确用法 [英] QEventLoop proper usage

查看:2769
本文介绍了QEventLoop的正确用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怀疑我应该如何使用QEventLoop.我有2段代码,它们都对我有用(下载Web资源).

第一个:

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()?我在某个地方找到了第二个解决方案,但是它对我来说似乎不合适,因此我将其修改为第一段代码.

解决方案

我同意@ Mher-Didaryan的观点,即事件循环由第二个代码片段中的代码loop.exec();行开始,因此永远不会退出.这是因为SIGNAL和SLOT之间的 connect()是针对与通过EventLoop loop;指示的事件循环不同的事件循环进行的.

在第一个代码段的情况下,逻辑取决于与一个& amp;关联的finished(QNetworkReply*)信号.相同的GET请求被发送到两个不同的事件循环.

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

manager->get( request ) ;发出finished(QNetworkReply*)信号之后,

可以很好地执行.对于包含很小文件或响应的GET类型HTTP操作,可能会发生这种情况.在这种情况下,由第一个代码段中的loop.exec();开始的事件循环也不会退出.我想这就是@ Mher-Didaryan在他的答案中也在查询的内容.

也许您可以使用下面的QEventLoop逻辑来处理以下负面执行情况

  1. 对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;
    

I have doubts how should I use QEventLoop. I have 2 pieces of code, both of them work for me (get web resource downloaded).

First one:

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

Second one:

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

What I want to know is which one should I use. I mean, does the event loop quit in the second one after signal is emmited? Or do I have to call quit() like in the first one? I found the second solution somewhere but it didn't seem proper to me so I modified it into first piece of code.

解决方案

I agree with @Mher-Didaryan - that the event loop started by following line of code loop.exec(); in the 2nd code snippet - will never exit. This is because the connect() between the SIGNAL and SLOT is being done for a different event loop than the event loop indicated through EventLoop loop; .

In the case of the 1st code snippet, the logic depends on the finished(QNetworkReply*) signal associated with one & same GET request being emitted to two different event loops. But it is quite possible that

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

may well execute after the manager->get( request ) ; has emitted the finished(QNetworkReply*) signal. Maybe it can happen for a GET type HTTP operation involving a very small file or response. In such a scenario the event loop started out by the loop.exec(); in the 1st code snippet will also not exit. I guess this is what @Mher-Didaryan is also querying in his answer.

Maybe you can use the below QEventLoop logic that would handle the following negative execution scenarios too

  1. Timing out of the GET request (say due to network connectivity issues)
  2. Error type response from server side of network

    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;
    

这篇关于QEventLoop的正确用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆