0

I am trying to create a thread (HttpWorker) that when required wakes up and sends a http request. I would like this to be done in a single thread. I am using Qt for the implementation.

The way I thought i would do it is to have a class MyHttpWorker, move it to another thread, connect the slots/signals etc. Then on thread start I would use QNetworkAccessManager to call get requests. I would use QWaitCondition to pause the thread after the request has been sent and I would resume this thread whenever I need to send another one.

However, when I pause the httpworker thread, the FinishedSlot is not called at all. If I use the class to simply call one http request, it executes with no problem. So the problem is connected to QWaitCondition (or just freezing the threads in general).

I could simply create and destroy one worker and thread for each request I have, but I require to send lot of http requests, so I think this method would be way too consuming (creating threads and destroying them over and over).

I appreciate any help I can get.

Here is my code:

MyHttpWorker.h

#include <QNetworkReply>
#include <QDebug>
#include <QObject>
#include <QNetworkAccessManager>
#include <QThread>
#include <QWaitCondition>
#include <QMutex>    

class MyHttpWorker : public QObject
    {
        Q_OBJECT

        QNetworkAccessManager* nam;        
        QMutex syncPause;
        QWaitCondition pauseCond;        

    public:
        explicit MyHttpWorker(QObject *parent = 0);        
        void MyWake();            
    public slots:        
         void SetTheThread(QThread* thread);
         void MyStart();        
         void finishedSlot(QNetworkReply* reply);            
    };

MyHttpWorker.cpp

MyHttpWorker::MyHttpWorker(QObject *parent) :
    QObject(parent)
{
    nam = new QNetworkAccessManager(this);
    QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));    
}

void MyHttpWorker::finishedSlot(QNetworkReply* reply)
{
    qDebug() << "Finished"; //This slot is never even reached, when i used QWaitCond...
    if (reply->error() == QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QString string(bytes);
        qDebug() << string;
    }else
    {
        qDebug() << reply->errorString();
    }
    reply->deleteLater();
}

void MyHttpWorker::SetTheThread(QThread* thread){
    QObject::connect(thread,SIGNAL(started()),this,SLOT(MyStart()));
}

void MyHttpWorker::MyWake(){    
    pauseCond.wakeAll();
}

void MyHttpWorker::MyStart(){    
    qDebug() << "Start" ; 

    while(true){

        syncPause.lock();    
        qDebug() << "thread waiting...";
        pauseCond.wait(&syncPause);
        qDebug() << "thread resumed.";
        syncPause.unlock();

        //sending the actual request here
        QNetworkRequest myRequest;
        myRequest.setUrl(QUrl("http://www.google.com"));
        nam->get(myRequest);



    }

}

main.cpp

#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <myhttpworker.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

   //create the worker, thread and launch it... (worker is waiting by default)
    MyHttpWorker* worker = new MyHttpWorker;    
    QThread* httpThread = new QThread;    
    worker->SetTheThread(httpThread);
    worker->moveToThread(httpThread);    
    httpThread->start();

   //try and send 5 requests ...
     for(int i=0;i<5;i++){
         qDebug() << "Unpausing";    
         QThread::currentThread()->msleep(1000);    
         worker->MyWake();    
     }

    return a.exec();
}

1 Answer 1

4

don't create an infinite loop but let the even loop handle it:

void MyHttpWorker::MyWake()
{
    QMetaObject::invokeMethod(this,"doSend");
    //send to the event loop
}

// new slot
void MyHttpWorker::doSend(){    
    //sending the actual request here
    QNetworkRequest myRequest;
    myRequest.setUrl(QUrl("http://www.google.com"));
    nam->get(myRequest);
}
//and remove the myStart and all that synchronisation

then when you want to stop it just send a quit to the thread. I suggest you also connect the finished signal of the thread to the deleteLater slot of MyHttpWorker

Sign up to request clarification or add additional context in comments.

2 Comments

It works, thank you :) I just want to ask if you could clarifiy on "I suggest you also connect the finished signal of the thread to the deleteLater slot of MyHttpWorker". You lost me there.
in setTheThread so it gets deleted when he thread stops (which happens only after someone calls quit)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.