Singleton QNetworkAccessManager not directing the response to desired form

爷,独闯天下 提交于 2020-01-16 01:13:12

问题


In a small Qt application, I have a NetworkAccessManager(NAM) wrapped in a singleton class. NAM object of this class is used by four independent form classes. Each form class fires a request to a separate php (and php takes at least 3 seconds with sleep(3)).

Now there are two cases:

Case I: When NAM, for each form, is connected to form's slot IN CONSTRUCTOR. In this case, when i send requests from all four forms simultaneously; all the responses are directed to just one form (the one that was first in firing the request) and not to the form that requested it.

Case II: When NAM is connected (for firing request) and disconnected (when response is received) to form's slot IN FUNCTIONS (and not constructor). In this case, when i send requests from all four forms simultaneously (i.e. in less than 3 seconds); then only the first response is returned and the rest never returned. This is in accordance with the code as singleton NAM was disconnected as soon as it received the reply for the first request. Therefore other requests could not be processed.

All form classes are identical and use the same code. Here is the code (Case II specific):

void Request2::slotStartRequest(){
   m_Req2 = NetworkAccessManager::getInstance();
   connect(m_Req2, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotReplyFinished(QNetworkReply*)));
   QString postData = "value=222";
   m_Req2->post(QNetworkRequest(QUrl(path)), postData.toUtf8());
}

void Request2::slotReplyFinished(QNetworkReply *reply){
   disconnect(m_Req2, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotReplyFinished(QNetworkReply*)));
   ui->TEdit_Req2->setText(reply->readAll());
   reply->deleteLater();
}

Though the code for both cases are very similar. This code is Case II specific. For Case I, only change is that 'connect' and 'getInstance' codes are put in constructor (and there is no 'disconnect').

The code will work fine with one NetworkAccessManager object per form class.

But how do I achieve the desired behaviour (with one NAM for whole application) that response is directed only to the form that requested it and also the requests for other forms should not be affected ?


回答1:


The NAM function post() creates a new QNetworkReply instance to manage that request. It is possible to connect directly to QNetworkReply signals instead of signals of QNetworkAccessManager:

void Request2::slotStartRequest(){
   QString postData = "value=222";
   QNetworkAccessManager *nam = NetworkAccessManager::getInstance();
   m_Reply = nam->post(QNetworkRequest(QUrl(path)), postData.toUtf8());    
   connect(m_Reply, SIGNAL(finished()), this, SLOT(slotReplyFinished()));
}

Now only this instance of QNetworkReply *m_Reply can call the signal of this. Note that there is no QNetworkReply *reply argument in the finished() signal:

void Request2::slotReplyFinished(){
   ui->TEdit_Req2->setText(m_Reply->readAll());
   m_Reply->deleteLater();
}



回答2:


My suggestion (what I do) is to keep track of which object made the request on the manager, perhaps update your manager to take in the object pointer

m_Req2->post(QNetworkRequest(QUrl(path)), postData.toUtf8(), this);

Then on the Manager, use that pointer and use the QMetaObject to invoke the method, instead of emitting a signal: http://doc.qt.io/qt-5/qmetaobject.html#invokeMethod.

So you get something like this, on the Manager

QMetaObject::invokeMethod(obj, "slotReplyFinished", Qt::DirectConnection,
                      Q_ARG(QNetworkReply*, reply));

(not tested, but you should get the idea)

[edit: fixed code]



来源:https://stackoverflow.com/questions/33537874/singleton-qnetworkaccessmanager-not-directing-the-response-to-desired-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!