PDA

View Full Version : QNetworkAccessManager does not work from QRunnable



luk_man_
24th October 2019, 19:07
Hello

I have the following code:

Below is a Worker class which is QRunnable object. As you know, it is started from QThreadPool.

class Worker : public QObject, public QRunnable
{
Q_OBJECT
public:
Worker();

protected:
virtual void run();
};


void Worker::run()
{
Sender sender;
sender.send({"text1", "text2"});
}

The sender.send() method:


void DataSender::send(const QList<QString>& data)
{
QUrl serviceUrl = QUrl(given_ip_addr);
QNetworkRequest request(serviceUrl);
QJsonObject json;
for (auto& line : data)
json.insert("data", line);
QJsonDocument jsonDoc(json);
QByteArray jsonData= jsonDoc.toJson();
request.setHeader(QNetworkRequest::ContentTypeHead er,"application/json");
request.setHeader(QNetworkRequest::ContentLengthHe ader,QByteArray::number(jsonData.size()));
QNetworkReply *reply = _networkMgr.post(request, jsonData);
}


Generally, the problem is: there is no any messages send to the endpoint given_ip_addr. No messages are received by the endpoint.

I think, the problem is in the running QNetworkAccessManager in the new thread, because I have tested another solution - I ran exactly the same send method in MAIN thread of whole application and there weren't any problems.

Do you have any idea? Unfortunately, I did not find anything in google about such problem.

Best Regards!

d_stranz
24th October 2019, 19:54
Every variable you define in your send() method is allocated on the stack, and thus will go out of scope as soon as the function exits. This includes the pointer to the QNetworkReply instance and your json data. From the documentation for QNetworkAccessManager::post():


data must be open for reading and must remain valid until the finished() signal is emitted for this reply.

Post operations are processed asynchronously, so you can't define your data as a variable that will go out of scope before the request completes.

You should spend some time trying to understand the documentation for QNetworkAccessManager and the examples and tutorials supplied with your Qt distribution. It is clear from your posts and the questions you are asking that you do not understand how this class should be used.

luk_man_
25th October 2019, 01:03
Every variable you define in your send() method is allocated on the stack, and thus will go out of scope as soon as the function exits. This includes the pointer to the QNetworkReply instance and your json data. From the documentation for QNetworkAccessManager::post():



Post operations are processed asynchronously, so you can't define your data as a variable that will go out of scope before the request completes.

You should spend some time trying to understand the documentation for QNetworkAccessManager and the examples and tutorials supplied with your Qt distribution. It is clear from your posts and the questions you are asking that you do not understand how this class should be used.

Ok, so if it so clear for you, run such code in your IDE and add some QThread::sleep at the end of run() method. Of course, calling sender.send() code is not the only one in run() method and using sleep() method is does not help to resolve this issue. Are my arguments correct?

luk_man_
25th October 2019, 08:09
I meant that adding sleep, checks the network manager variable and it is ok during sending and waiting for QNetworkReply. Unfortunately, it still does not work.

ChristianEhrlicher
25th October 2019, 17:12
Every variable you define in your send() method is allocated on the stack, and thus will go out of scope as soon as the function exits.
It's even better - take a look at the run() method... :)

d_stranz
25th October 2019, 18:22
It's even better - take a look at the run() method...

Yes, saw that. But one step at a time. Eventually the OP will run out of hammers and might start to think about the problem and the approach.