Using QThread and QNetworkAccessManager



  • I am trying to make my desktop app execute some Internet lookups in the background and planned on having the background thread send a signal to my main thread when completed w/the data found or network error. I am starting the thread just fine but it never seems to execute. The output is:

    @Running QrzCallbook thread
    QUrl( "http://localhost/xml?callsign=AA1AA" )@

    The header is:

    @#ifndef QRZCALLBOOK_H
    #define QRZCALLBOOK_H

    #include <QThread>
    #include <QUrl>
    #include <QNetworkAccessManager>
    #include <QNetworkReply>

    class QrzCallbook : public QThread
    {
    Q_OBJECT

    public:
    explicit QrzCallbook(QObject *parent = 0) : QThread(parent) {}

    virtual void lookup(QString call) {
        callsign = call;
        start();
    }
    
    virtual void run();
    

    signals:
    void stationData(const QString& name);
    void networkError(const QString errorMessage);
    void parseError(const QString errorMessage);

    private slots:
    void downloadFinished();

    private:
    QNetworkAccessManager *netAccessMgr;
    QNetworkReply *netReply;
    QString callsign;
    };

    #endif // QRZCALLBOOK_H@

    The class file is:

    @#include <QNetworkRequest>

    #include "SmartLog.h"
    #include "QrzCallbook.h"

    void QrzCallbook::run()
    {
    qDebug() << "Running QrzCallbook thread";

    QUrl thisUrl("http://localhost/xml");
    thisUrl.addQueryItem("callsign", callsign);
    
    qDebug() << thisUrl;
    
    netAccessMgr = new QNetworkAccessManager;
    netReply = netAccessMgr->get(QNetworkRequest(thisUrl));
    connect(netReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
    

    }

    void QrzCallbook::downloadFinished()
    {
    qDebug() << "Download has finished";
    netAccessMgr->deleteLater();
    netReply->deleteLater();

    if (netReply->error()) {
        qDebug() << netReply->errorString();
        emit networkError(netReply->errorString());
        return;
    }
    
    qDebug() << netReply->readAll();
    
    emit stationData("Not Implemented");
    

    }
    @

    Any thoughts on why the downloadFinished() slot is never run?

    Jeremy



  • I think I understand what's going on here. A request is made to download a web page, signals/slots are connected and then my thread terminates before the results are returned, thus I never get a download.

    How do I tell my thread to remain active until a download is complete?



  • why do you want to use threads for that? in qnetworkaccessmanager all requests are asynchronus already



  • I originally had it to not use a thread and when doing a lookup the GUI hangs for about 1 1/2 seconds when the action is executed. With this particular action if call server #1 doesn't have the callsign on file then a subsequent request will go out to another callbook server. That created another 1 1/2 second GUI freeze. I am not certain where the "freeze" occurs at. Here is my non-threaded code output:

    @Running QrzCallbook thread: 0
    Requesting: 0
    Done Requesting: 1
    Download has finished: 1765
    Reading data: 1765
    Done reading: 1765@

    There is no delay in the "run" method, nor any in the "downloadFinished" method but the GUI hangs. By hang I mean I cannot use my arrow keys to move around in the field, tab ceases to work and clicking with my mouse on any new field does not function for about 1 1/2 seconds. The event is triggered in a slot responding to a QLineEdit's textChanged signal.

    Here is the non-threaded source .h:

    @class QrzCallbook : public QObject
    {
    Q_OBJECT

    public:
    explicit QrzCallbook(QObject *parent = 0) : QObject(parent) {}

    virtual void lookup(QString call) {
        callsign = call;
        run();
    }
    
    virtual void run();
    

    signals:
    void stationData(const QString& name);
    void networkError(const QString errorMessage);
    void parseError(const QString errorMessage);

    private slots:
    void downloadFinished();

    private:
    QNetworkAccessManager *netAccessMgr;
    QNetworkReply *netReply;
    QString callsign;
    QTime timer;
    };@

    And the non-threaded .cpp:

    @void QrzCallbook::run()
    {
    timer.start();

    qDebug() << "Running QrzCallbook thread: " << timer.elapsed();
    
    QUrl thisUrl("http://localhost/xml");
    
    qDebug() << "Requesting: " << timer.elapsed();
    netAccessMgr = new QNetworkAccessManager;
    netReply = netAccessMgr->get(QNetworkRequest(thisUrl));
    connect(netReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
    qDebug() << "Done Requesting: " << timer.elapsed();
    

    }

    void QrzCallbook::downloadFinished()
    {
    qDebug() << "Download has finished: " << timer.elapsed();
    netAccessMgr->deleteLater();
    netReply->deleteLater();

    if (netReply->error()) {
        qDebug() << netReply->errorString();
        emit networkError(netReply->errorString());
        return;
    }
    
    qDebug() << "Reading data: " << timer.elapsed();
    QByteArray data = netReply->readAll();
    qDebug() << "Done reading: " << timer.elapsed();
    
    emit stationData("Not Implemented");
    

    }@

    So... to answer your question, I am trying to get rid of the 1 1/2 second delay that occurs.

    Jeremy



  • try placing your connect line in constructor



  • Ah, I got it. I didn't include an event loop in my thread. Simply adding exec(); to the end of my run() method caused everything to work like a charm.



  • Oh, also one more thing. I did add an exit() to my downloadFinished slot. Further, this has caused my main gui to remain responsive. There is no 1 1/2 second pause when the download is taking place.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.