PDA

View Full Version : Event Driven Programming (using QNetworkAccessManager)



SpiceWeasel
16th April 2018, 13:35
Hello,

I've a couple of questions about event-driven programming.

I was recently handed some code the uses QNetworkAccessManager to communicate with a RIAK TS database. After calling QnetworkAccessManager::post(...), the author creates and event loop and waits for the QNetworkReply to finish. This approach is problematic because this code is being inserted into a GUI application, which of course has its own event loop. I've experienced cases where the author's event loop never returns; resulting in an application hang.

My first question is: Are event loops within event loops a bad practice in event-driven programming?

The second question is how to handle an operation that could take awhile or never produce a result?

I am working on an Open function that must query the RIAK database for a list of data sets to open. Since the operation is not guaranteed to return immediately (or at all), I'd like to know how I should approach handling it. Right now, I am thinking that I need to break the Open function into smaller functions and somehow connect those functions to the results of the query. But then the Open function seems like it should be atomic…

Not sure how to handle this, and am looking for advice.

Thanks!

SpiceWeasel
18th April 2018, 16:23
Since I have had to work this problem, I've come up with answers to my own questions and thought I would share them. However, I am still looking for advice, as my answers might be wrong.

Answer to question #1 : Yes. Doing anything in an event-driven program that you know has the potential to lock the application is (most of the time) a bad practice.

Answer to question #2 : From what I've observed, a QNetworkRequest that has been posted generates three possible outcomes:
1) The request is honored, and the QNetworkReply that is returned has the results, or...
2) The request fails, and the QNetworkReply that is returned contains an error message, or...
3) Nothing is returned. No signals are generated. (This had occurred two separate times, and I am at a loss to explain why.)

I am still uncertain how to handle #3, but have come up with a solution for #1 and #2 as demonstrated by the following function:



void MainWindow::PostQuery(QByteArray Query, NRMemFn SuccessFunction, NRMemFn FailureFunction)
{
QNetworkReply* p_reply = m_Manager.post(m_QueryRequest, Query);
connect(p_reply, &QNetworkReply::finished, [=](){ (this->*SuccessFunction)(p_reply); p_reply->disconnect(); p_reply->deleteLater();} );
connect(p_reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), [=](){ (this->*FailureFunction)(p_reply); p_reply->disconnect(); p_reply->deleteLater();} );
}


This PostQuery function takes three arguments: a query and two pointers to member functions. The pointers to member functions are connected to the signals that the QNetworkReply will generate for cases #1 and #2. Lamba functions provide the needed "glue".

My Open function now just calls PostQuery with success and failure function pointers. Of course, this does not solve case #3; nor does it handle the (sub?) case of the results being delayed. (When you click Open, you expect to see something immediately, but the QNetworkReply is not guaranteed to be generated at any specific time -- or at all!)

Lesiok
19th April 2018, 06:54
3) Nothing is returned. No signals are generated. (This had occurred two separate times, and I am at a loss to explain why.)

I am still uncertain how to handle #3...
Use QTimer::singleShot connected to code that supports this situation.