简体   繁体   English

QEventLoop的正确用法

[英]QEventLoop proper usage

I have doubts how should I use QEventLoop . 我怀疑我应该如何使用QEventLoop I have 2 pieces of code, both of them work for me (get web resource downloaded). 我有2段代码,它们都对我有用(下载Web资源)。

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? 还是我必须像第一个一样调用quit() 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(); 我同意@ Mher-Didaryan-事件循环通过以下代码行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; 这是因为信号和插槽之间的connect()是针对与EventLoop loop;指示的事件循环不同的事件循环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. 在第一个代码段的情况下,逻辑取决于与一个&相同GET请求相关联的finished(QNetworkReply*)信号被发送到两个不同的事件循环。 But it is quite possible that 但是很有可能

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

may well execute after the manager->get( request ) ; 可以在manager->get( request ) ;之后执行manager->get( request ) ; has emitted the finished(QNetworkReply*) signal. 发出finished(QNetworkReply*)信号。 Maybe it can happen for a GET type HTTP operation involving a very small file or response. 对于包含很小文件或响应的GET类型HTTP操作,可能会发生这种情况。 In such a scenario the event loop started out by the loop.exec(); 在这种情况下,事件循环由loop.exec(); in the 1st code snippet will also not exit. 第一个代码段中的代码也不会退出。 I guess this is what @Mher-Didaryan is also querying in his answer. 我想这就是@ Mher-Didaryan在他的答案中也在查询的内容。

Maybe you can use the below QEventLoop logic that would handle the following negative execution scenarios too 也许您可以使用下面的QEventLoop逻辑来处理以下否定执行方案

  1. Timing out of the GET request (say due to network connectivity issues) GET请求超时(例如由于网络连接问题)
  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 ie 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; 

In your second example event loop will never quit, on the other hand in your first example the loop will quit when finished(QNetworkReply*) emits. 在您的第二个示例中,事件循环永远不会退出,而在您的第一个示例中,该循环将在finished(QNetworkReply*)发出时退出。 But what if manager->get( request ); 但是如果manager->get( request );怎么办manager->get( request ); cause finished(QNetworkReply*) signal to be emited before you connect loop's quit to it? 导致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();

And also you need to somehow handle situation where manager does not emit SIGNAL(finished(QNetworkReply*)) at all. 而且,您还需要以某种方式处理管理器根本不发出SIGNAL(finished(QNetworkReply*))情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM