Singleton QNetworkAccessManager不会将响应指向所需的表单

时间:2015-11-05 06:18:25

标签: qt singleton qnetworkaccessmanager

在一个小型Qt应用程序中,我将NetworkAccessManager(NAM)包装在单例类中。此类的NAM对象由四个独立的表单类使用。每个表单类都会向一个单独的php发出一个请求(而php在睡眠时至少需要3秒钟(3))。

现在有两种情况:

案例I:当每个表单的NAM连接到表单的插槽IN CONSTRUCTOR时。     在这种情况下,当我同时发送来自所有四个表单的请求时;所有回复都只针对一个表单(首先触发请求的表单)而不是表单请求它。

情况II:当NAM连接(用于触发请求)和断开连接(当收到响应时)以形成插槽IN FUNCTIONS(而不是构造函数)。     在这种情况下,当我同时发送来自所有四种表格的请求时(即在不到3秒内);然后只返回第一个响应,其余的都没有返回。这与代码一致,因为单例NAM在收到第一个请求的回复后立即断开连接。因此无法处理其他请求。

所有表单类都相同并使用相同的代码。这是代码(具体案例II):

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();
}

虽然这两种情况的代码非常相似。此代码特定于案例II。对于案例I,只有更改是'connect'和'getInstance'代码放在构造函数中(并且没有'disconnect')。

对于每个表单类,一个NetworkAccessManager对象的代码可以正常工作。

但是,如何实现所需的行为(对于整个应用程序只有一个NAM),响应仅针对请求它的表单,而且其他表单的请求也不应受到影响?

2 个答案:

答案 0 :(得分:2)

NAM函数post()创建一个新的QNetworkReply实例来管理该请求。可以直接连接到QNetworkReply信号,而不是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()));
}

现在只有QNetworkReply *m_Reply的这个实例可以调用this的信号。请注意,QNetworkReply *reply信号中没有finished()参数:

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

答案 1 :(得分:0)

我的建议(我所做的)是跟踪哪个对象在管理器上发出请求,或者更新管理器以接收对象指针

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

然后在Manager上,使用该指针并使用QMetaObject调用该方法,而不是发出信号:http://doc.qt.io/qt-5/qmetaobject.html#invokeMethod

所以你在经理上得到这样的东西

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

(未经过测试,但您应该明白这一点)

[编辑:固定代码]