Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt FileDownloader class adaptation for threading



  • Hello Everyone!

    I'm new to threads and Qt in general, so this question will probably seem like trivial to someone, sorry for that. So let's get to the point: I'm trying to adapt the (Qt example downloader class) to be used in a separate thread as part of a virtual proxy, so I modified it slightly in the following manner:

    // filedownloader.h
    class FileDownloader : public QObject
    {
     Q_OBJECT
     public:
      FileDownloader() {}
      explicit FileDownloader(const QUrl& Url, QObject *parent = 0);
      virtual ~FileDownloader();
      QByteArray downloadedData() const;
    
     signals:
      void downloaded();
    
     private slots:
      void startDownload();
      void fileDownloaded(QNetworkReply* pReply);
    
     private:
      QUrl imageUrl;
      QNetworkAccessManager m_WebCtrl;
      QByteArray m_DownloadedData;
    };
    
    // filedownloader.cpp
    FileDownloader::FileDownloader(const QUrl& Url, QObject *parent) :
     QObject(parent), imageUrl{Url} {}
    
    FileDownloader::~FileDownloader() { }
    
    void FileDownloader::startDownload()
    {
        connect(
         &m_WebCtrl, SIGNAL (finished(QNetworkReply*)),
         this, SLOT (fileDownloaded(QNetworkReply*))
         );
    
        QNetworkRequest request(imageUrl);
        m_WebCtrl.get(request);
    // rest of the class definitions...
    }
    

    I moved the contents of the constructor to a separate "startDownload" function (which is also a slot) and I try to use this class in the following manner:

    // trying to use downloader
     thread = new QThread();
     downloader = new FileDownloader(imageURL);
     downloader->moveToThread(thread);
     connect(thread, SIGNAL(started()), downloader, SLOT(startDownload()));
     connect(downloader, SIGNAL(downloaded()), this, SLOT(loadImage()));
     connect(downloader, SIGNAL(downloaded()), thread, SLOT(quit()));
     connect(downloader, SIGNAL(downloaded()), downloader, SLOT(deleteLater()));
     connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
     thread->start();
    

    The problem is that it doesn't work. At runtime I get the following error message:

    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QNetworkAccessManager(0x7fe54c008858), parent's thread is QThread(0x564bee0a4910), current thread is QThread(0x564bee38d7c0)
    

    I went through it with the debugger, and the error is emitted while trying to execute the following line:

    // in startDownload() function:
        m_WebCtrl.get(request);
    

    Could somebody give some suggestions how to make this work? I thought all the functions of this class would now be executed in a separate thread.

    Thanks in advance.


  • Lifetime Qt Champion

    Since all QNetworkManager actions are already async in a separate thread there is no need for another thread here at all.


Log in to reply