0

I am trying to multiple request with QNetworkAccessManager even I connect slots QNetworkAccessManager cant emit finished() signal.

Here is the code I implemented.

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

What's wrong in these codes? I cant figure it out.

Thank you.

11
  • Have you tried to hook the error signal? Commented Jan 8, 2014 at 7:01
  • You must return to the event loop to have the request being executed and the result being reported. Your code with the while loop and sleep looks like you block the event loop (until the result arrived?), thus the request isn't executed at all. Commented Jan 8, 2014 at 7:06
  • I.e., sleep() blocks the event loop and thus any event processing including network I/O. Also in a UI application, sleep() in the main thread is really bad practice, as it makes the UI unresponsive. Commented Jan 8, 2014 at 7:15
  • no it waits untill all threads are done. but qnetworkaccessmanager doesnt emit finished signal and the function waits here for nothing.i just want to be sure that all gets are done end of the function. Commented Jan 8, 2014 at 9:38
  • the problem is about while "(!waitWithFlag()) QThread::msleep(10);" end of the function is there a way wait these gets until all of them are done? Commented Jan 8, 2014 at 10:30

2 Answers 2

1

First of all you don't need a separate thread for QNetworkAccessManager as it internally runs in a separate thread (asynchronous) since Qt 4.8.1.

Secondly you are only connecting the last instance of QNetworkAccessManager with a finished slot, instead of doing that, connect each instance of QNetworkAccessManager with handleMultiRequest Slot and keep increasing the count whenever the slot is invoked. You don't need sleep and all that stuff, it is all event driven. So,

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()
   }
}
2
  • QNetworkAccessManager can have more than 6 thread run at sametime? Commented Jan 8, 2014 at 11:45
  • @VeyselBekirMacit That is for HttpPipelining, those six threads are for the same request. you can disable that feature programatically, Commented Jan 8, 2014 at 12:27
0

and I changed fucntions like Adnan idea

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

and

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()));
}
2
  • 1
    Local events loops are a completely inappropriate way to make asynchronous code appear synchronous. They are probably the most evil and pain-inducing construct in Qt I know of (as everything can happen before the exec() returns - leaving the application in an inconsistent unexpected state; just an example: "this" could be deleted). Using them without knowing exactly what one is doing will cause horror and pain in the long run. Better make the getAction() API asynchronous. Commented Jan 8, 2014 at 12:18
  • yes if one of them makes an error that loop will wait wait is better adding a timer to detect abnormal latency? Commented Jan 8, 2014 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.