问题
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