QNetworkAccessManager 不发出完成信号
Posted
技术标签:
【中文标题】QNetworkAccessManager 不发出完成信号【英文标题】:QNetworkAccessManager doesnt emit finished signal 【发布时间】:2014-01-08 03:13:57 【问题描述】:我正在尝试使用 QNetworkAccessManager 进行多个请求,即使我连接插槽 QNetworkAccessManager 也无法发出 finished() 信号。
这是我实现的代码。
void GetNetwork::getAction(QStringList *urls, QList<QByteArray> *result)
uint size=urls->size();
multiGetResult=result;
getUrls=urls;
setFlags();
for(uint x=0;x<size;x++)
int test=caluculateIndex(x);
getNAM[test]->get(QNetworkRequest(QUrl(urls->at(x))));
//qDebug()<<reply->readAll();
while (!waitWithFlag()) QThread::msleep(15);
delete threadFlag;
bool GetNetwork::setMultipleGet(uint number)
int diff=number-(getNAM.size()-1);
if(((getNAM.size()-1)+diff)<0)
return false;
for(int i=0;i<diff;i++)
getNAM.append(new QNetworkAccessManager(this));
connect(getNAM[getNAM.size()-1],SIGNAL(finished(QNetworkReply*)),this,SLOT(handleMultiRequest(QNetworkReply*)));
for(int i=diff;i<0;i++)
disconnect(getNAM[getNAM.size()-1],SIGNAL(finished(QNetworkReply*)),this,SLOT(handleMultiRequest(QNetworkReply*)));
delete getNAM[getNAM.size()-1];
getNAM.remove(getNAM.size()-1);
return true;
void GetNetwork::handleMultiRequest(QNetworkReply * reply)
int index=getUrls->indexOf(reply->url().toString());
if(reply->error()!=QNetworkReply::NoError||index==-1)
QString error=QString("Network Error file:%1 line:%2 error:%3")
.arg(__FILE__)
.arg(__LINE__)
.arg(reply->errorString());
emit errorOccured(error);
return;
multiGetResult->insert(index,reply->readAll());
threadFlag[index]=true;
这些代码有什么问题?我想不通。
谢谢。
【问题讨论】:
你有没有尝试hook错误信号? 您必须返回事件循环才能执行请求并报告结果。带有 while 循环和 sleep 的代码看起来像是阻塞了事件循环(直到结果到达?),因此根本不执行请求。 即,sleep() 会阻塞事件循环,因此会阻塞任何事件处理,包括网络 I/O。同样在 UI 应用程序中,主线程中的 sleep() 是非常糟糕的做法,因为它会使 UI 无响应。 不,它会等到所有线程都完成。但是 qnetworkaccessmanager 没有发出完成的信号,并且函数在这里等待什么。我只是想确保所有获取都在函数结束时完成。 问题是关于 while "(!waitWithFlag()) QThread::msleep(10);"函数的结尾有没有办法等到所有这些都完成? 【参考方案1】:首先,QNetworkAccessManager 不需要单独的线程,因为它在 Qt 4.8.1 之后在内部运行在单独的线程(异步)中。
其次,您仅将 QNetworkAccessManager 的最后一个实例与已完成的插槽连接,而不是这样做,而是将 QNetworkAccessManager 的每个实例与 handleMultiRequest Slot 连接,并在调用插槽时不断增加计数。你不需要睡眠之类的东西,这都是事件驱动的。 所以,
void GetNetwork::handleMultiRequest(QNetworkReply * reply)
int index=getUrls->indexOf(reply->url().toString());
if(reply->error()!=QNetworkReply::NoError||index==-1)
QString error=QString("Network Error file:%1 line:%2 error:%3")
.arg(__FILE__)
.arg(__LINE__)
.arg(reply->errorString());
emit errorOccured(error);
return;
count++;
if(count == num_get_requests)
emit
allDone()
【讨论】:
QNetworkAccessManager可以同时运行6个以上的线程吗? @VeyselBekirMacit 那是针对 HttpPipelining 的,那六个线程是针对同一个请求的。您可以通过编程方式禁用该功能,【参考方案2】:我改变了像 Adnan 想法这样的功能
void GetNetwork::handleMultiRequest(QNetworkReply * reply)
int index=getUrls->indexOf(reply->url().toString());
if(reply->error()!=QNetworkReply::NoError||index==-1)
QString error=QString("Network Error file:%1 line:%2 error:%3")
.arg(__FILE__)
.arg(__LINE__)
.arg(reply->errorString());
emit errorOccured(error);
return;
multiGetResult->insert(index,reply->readAll());
threadDoneCounter++;
if(threadDoneCounter==getUrls->size())
emit threadsAreDone();
和
void GetNetwork::getAction(QStringList *urls, QList<QByteArray> *result)
uint size=urls->size();
multiGetResult=result;
getUrls=urls;
threadDoneCounter=0;
for(uint x=0;x<size;x++)
int test=caluculateIndex(x);
getNAM[test]->get(QNetworkRequest(QUrl(urls->at(x))));
QEventLoop eLoop;
connect(this,SIGNAL(threadsAreDone()),&eLoop,SLOT(quit()));
eLoop.exec();
disconnect(this,SIGNAL(threadsAreDone()),&eLoop,SLOT(quit()));
【讨论】:
本地事件循环是使异步代码看起来同步的完全不合适的方式。它们可能是我所知道的 Qt 中最邪恶和最痛苦的构造(因为一切都可能在 exec() 返回之前发生 - 使应用程序处于不一致的意外状态;只是一个例子:“this”可以被删除)。从长远来看,在不知道自己在做什么的情况下使用它们会导致恐惧和痛苦。最好让 getAction() API 异步。 是的,如果其中一个发生错误,循环将等待等待,最好添加一个计时器来检测异常延迟?以上是关于QNetworkAccessManager 不发出完成信号的主要内容,如果未能解决你的问题,请参考以下文章
Qt QNetworkAccessManager 发出完成信号的长时间延迟
在发布模式下编译时不会发出 QNetworkAccessManager 完成信号(VS 2005)
QFtp或QNetworkaccessmanager因系统代理请求报错解决方案