Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?
-
This post is deleted!
-
@JonB said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
@Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
do {} while (!bDoneStats); // never breaks loop
When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....
I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.
-
@Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
I just realized I called 'connect' after the post, I will change the order and try again.
-
@Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.
This absolutely will not happen. Rather, your program will use up CPU time forever here, contributing to the entropy of The Universe :)
There are no multiple threads threads here. No signals or slots will fire while your loop executes. You will need a "wait for" event loop here instead, because you don't want to accept the original close event until this has completed. Look at QEventLoop::exec(). I don't know if there are consequences of calling this while inside
MainWindow::closeEvent()
. -
I've removed the do/while loop, I have re-ordered these statements:
connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats); reply = nam->post(*request, content);
This is part of an application that otherwise runs fine. 'exec' is called in another part of the program (main.cpp).
The code works if invoked at the beginning of the program. It only seems to fail when it is called at the end of a session.
What do I need to do to get it to work?
-
Hi,
One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.
In any case, there's no need to allocate QNetworkRequest on the heap.
-
@Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
'exec' is called in another part of the program (main.cpp).
I was talking about you putting an event loop here in your code:
QEventLoop loop; loop.exec();
That's how you have to do a "wait for", when you really need to, in Qt stuff.
-
@SGaist said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:
Hi,
One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.
YES! That's one of the solutions I tried to do, but couldn't figure out where to do it. Where, in the code, can I intercept an application 'quit', prior to closeEvent?
-
OK, here is the final, working solution. I am new to Qt and am not familiar with QEventLoop. I needed to see how the whole thing fitted together in order to understand.
void MainWindow::closeEvent(QCloseEvent *event) { QNetworkReply *reply; QUrl url("https://foo.com/bar.php?some&data"); if(!url.isValid()) { QString urlError = url.errorString(); qDebug() << "\n" << urlError << "\n"; } QNetworkRequest *request = new QNetworkRequest(url); request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain"); QByteArray content = "https://foo.com/bar.php?some&data"; QNetworkAccessManager *nam = new QNetworkAccessManager; if(request != NULL && nam != NULL ) { QEventLoop loop; // https://www.codeproject.com/Questions/1196636/Qnetworkaccesmanager-doesn-t-emit-finished-signal connect (nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()), Qt::DirectConnection); reply = nam->post(*request, content); loop.exec(); QNetworkReply::NetworkError netret = reply->error(); qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n"; QList<QByteArray> headers = reply->rawHeaderList(); QList<QByteArray>::iterator hit; for(hit = headers.begin(); hit != headers.end(); hit++) // is empty if failed qDebug() << *hit << reply->rawHeader(*hit); } event->accept(); QMainWindow::closeEvent(event); }
-
@Sprezzatura
I think this looks better :)Your code as it stands presumably leaks
QNetworkRequest *request = new QNetworkRequest(url);
andQNetworkAccessManager *nam = new QNetworkAccessManager;
. You could put these on the stack (no pointers, nonew
). And I think you're supposed todeleteLater()
theQNetworkReply *reply = nam->post(*request, content);
.You can get away without, but one day when you want examine your code for memory leaks with e.g.
valgrind
it will be better.