Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to run a task(particular function) independently without blocking my normal flow of code.
QtWS25 Last Chance

How to run a task(particular function) independently without blocking my normal flow of code.

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 4 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    HimanshuKaushik
    wrote on 31 Mar 2022, 11:04 last edited by
    #1

    Hello Guys, I am working on project where I need to Update GUI every 100 ms based on signals I'm getting from controller. In this I need to download a Log file which is present in my controller. I am getting that file using ftp(Qnetworkaccessmanager). I am able to do these task separately. But when I combine it together my UI freezes till the file is downloaded.

    I want my UI to update every 100 ms and also want log file to download in background. Please suggest any method.

    while searching on Google I found that I can use Qthread to run it independently. so I have tried one example where I run a counter(increment by 1) every 1 sec and I have download button which triggers my thread and downloads the file. But still the counter(UI) freezes till the complete file is downloaded and then continues to increment by 2 which I dont know whys its happening.

    I will pasted the whole code down so that u guys can help me figure how to run task independently without waiting for one task.
    I am not expert so there might me logic error or something please feel free to suggest them too.

    Code:
    Project Name : test5
    All Header files

    mythread.h

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    
    #include <QThread>
    #include <QMutex>
    
    
    class MyThread : public QThread
    {
       Q_OBJECT
    
    public slots:
        void stopRunning();
    
    protected:
       virtual void run();
    
    signals:
    //   void signalValueUpdated(QString);
    
    private:
        bool isRunning;
    
    };
    
    
    
    
    #endif // MYTHREAD_H
    

    qftpfiledownload.h

    #ifndef QFTPFILEDOWNLOAD_H
    #define QFTPFILEDOWNLOAD_H
    
    //HK 29/3/22
    #include<qobject.h>
    #include<QUrl>
    #include<QtNetwork/QNetworkAccessManager>
    #include<QtNetwork/QNetworkRequest>
    #include<QtNetwork/QNetworkReply>
    #include<QEventLoop>
    
    class QftpFileDownload
    {
    public:
    //    QNetworkReply *reply;   //HK 29/3/22
      QftpFileDownload(QString QftpPathName = "",QString QftpUserName = "", QString QftpPassword = "", QString QftpOutputName ="");
    //    QNetworkAccessManager *nam;
    //    QEventLoop loop;
      QString getPathName();
      QString getUserName();
      QString getPassword();
      QString getOutputName();
      void File_Download();
    private:
        QString QftpPathName;   //HK 30/3/22 This requires full path with textfile name eg ."ftp://169.254.10.102/test.txt"
        QString QftpUserName;
        QString QftpPassword;
        QString QftpOutputName;
    
    
    
    };
    
    #endif // QFTPFILEDOWNLOAD_H
    
    

    test5.h

    #ifndef TEST5_H
    #define TEST5_H
    
    #include <QMainWindow>
    #include<QString>
    #include<QTimer>
    #include"mythread.h"
    
    namespace Ui {
    class test5;
    }
    
    class test5 : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit test5(QWidget *parent = 0);
        ~test5();
     unsigned int counter = 0;
        void display_time();
    
    private slots:
        void on_pushButton_clicked();
        void updateTimer();
    signals:
        void download_button_clicked();
    
    private:
        Ui::test5 *ui;
        QTimer *Timer;
        MyThread thread;
    };
    
    #endif // TEST5_H
    
    

    All source files

    main.cpp

    #include "test5.h"
    #include <QApplication>
    #include"ui_test5.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        test5 w;
        w.show();
    
    
    
       return a.exec();
    }
    
    

    mythread.cpp

    #include "mythread.h"
    #include <QString>
    #include"qftpfiledownload.h"
    
    void MyThread::run()
    {
        qDebug("Thread id inside run %d",*((int*)QThread::currentThreadId()));
    
       
        isRunning = 1;
        QftpFileDownload object("ftp://169.254.10.102/test_100mb.txt","Administrator","Nopass123","Mytesting100.txt");
    
        object.File_Download();
    
    
    
    }
    
    void MyThread::stopRunning()
    {
        isRunning = 0;
    }
    
    

    qftpfiledownload.cpp

    #include "qftpfiledownload.h"
    //HK 29/3/22
    #include<QUrl>
    #include<QtNetwork/QNetworkAccessManager>
    #include<QtNetwork/QNetworkRequest>
    #include<QtNetwork/QNetworkReply>
    #include<QEventLoop>
    #include<QFile>
    
    #include"test5.h"
    
    
    
    QftpFileDownload::QftpFileDownload(QString QftpPathName, QString QftpUserName, QString QftpPassword, QString QftpOutputName)
    {
        this->QftpPathName = QftpPathName;
        this->QftpUserName = QftpUserName;
        this->QftpPassword = QftpPassword;
        this->QftpOutputName = QftpOutputName;
    }
    
    QString QftpFileDownload::getPathName()
    {
        return QftpPathName;
    }
    
    QString QftpFileDownload::getUserName()
    {
        return QftpUserName;
    }
    
    QString QftpFileDownload::getPassword()
    {
        return QftpPassword;
    }
    
    QString QftpFileDownload::getOutputName()
    {
        return QftpOutputName;
    }
    
    void QftpFileDownload::File_Download()
    {
        QEventLoop loop;
    
     QNetworkAccessManager *nam = new QNetworkAccessManager();
     QObject::connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    qDebug()<<"Inside Function";
    test5 time;
    time.display_time();
    //    QUrl url2("ftp://169.254.10.102/test.txt");
     QUrl url2(QftpPathName);
    //      url2.setPassword("Nopass123");
    //      url2.setUserName("Administrator");
     url2.setPassword(QftpPassword);
     url2.setUserName(QftpUserName);
      QNetworkRequest req(url2);
      QNetworkReply *reply = nam->get(req);
      loop.exec();
    
      QFile file(QftpOutputName);
      file.open(QIODevice::WriteOnly | QIODevice::Text);
      QTextStream out(&file);
      out<< reply->readAll();
      file.close();
      reply->deleteLater();
    
      qDebug()<<"Last line";
      time.display_time();
    }
    
    

    test5.cpp

    #include "test5.h"
    #include "ui_test5.h"
    #include"qftpfiledownload.h"
    #include"time.h"
    //#include"mythread.h"
    
    test5::test5(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::test5)
    {
        ui->setupUi(this);
    
        Timer = new QTimer();
        connect(Timer,SIGNAL(timeout()),this,SLOT(updateTimer()));
        Timer->start(1000);
        qDebug("Thread id %d",*((int*)QThread::currentThreadId()));
    
        //When the start button is pressed, invoke the start() method in the counter thread
        QObject::connect(this,SIGNAL(download_button_clicked()),&thread,SLOT(start()), Qt::QueuedConnection);
    
        //When the stop button is pressed, invoke the stop() method in the counter thread
        //QObject::connect(stopButton,SIGNAL(clicked()),&thread,SLOT(stopRunning()), Qt::QueuedConnection);
    
        //When the counter thread emits a signal saying its value has been updated, reflect that change in the lineEdit field.
        //QObject::connect(&thread,SIGNAL(signalValueUpdated(const QString&)),lineEdit,SLOT(setText(const QString&)), Qt::QueuedConnection);
    
    //    if(counter % 1000 == 0)
    //    {
    //        ui->Counter->setText(QString(counter));
    //        counter =0;
    //    }
    }
    
    test5::~test5()
    {
        delete ui;
    }
    
    void test5::on_pushButton_clicked()
    {
    //    QftpFileDownload object("ftp://169.254.10.102/test_100mb.txt","Administrator","Nopass123","Mytesting100.txt");
    
    //    object.File_Download();
        emit download_button_clicked();
    }
    
    void test5::updateTimer()
    {
        static unsigned int Counter=0;
    
        ui->Counter->setText(QString::number(Counter));
        Counter++;
    }
    
    void test5::display_time()
    {
        time_t rawtime;
        struct tm * timeinfo;
        time(&rawtime);
        timeinfo = localtime( &rawtime);
        qDebug("%02d:%02d:%02d\n",timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
    //	char output[8];
    //	sprintf(output,"%02d:%02d:%02d",timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
    //	printf("%s\t",output);
    //	printf("%d\n",sizeof(output));
    
    
    }
    
    

    test5.ui
    test5_UI.png

    I will paste the pro file too so that u guys can copy this and workout on this project

    test5.pro

    #-------------------------------------------------
    #
    # Project created by QtCreator 2022-03-31T10:12:10
    #
    #-------------------------------------------------
    
    QT       += core gui network
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = test5
    TEMPLATE = app
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    
    SOURCES += \
            main.cpp \
            test5.cpp \
        qftpfiledownload.cpp \
        mythread.cpp
    
    HEADERS += \
            test5.h \
        qftpfiledownload.h \
        mythread.h
    
    FORMS += \
            test5.ui
    
    

    Thanks in advance

    P 1 Reply Last reply 31 Mar 2022, 13:17
    0
    • H HimanshuKaushik
      31 Mar 2022, 11:04

      Hello Guys, I am working on project where I need to Update GUI every 100 ms based on signals I'm getting from controller. In this I need to download a Log file which is present in my controller. I am getting that file using ftp(Qnetworkaccessmanager). I am able to do these task separately. But when I combine it together my UI freezes till the file is downloaded.

      I want my UI to update every 100 ms and also want log file to download in background. Please suggest any method.

      while searching on Google I found that I can use Qthread to run it independently. so I have tried one example where I run a counter(increment by 1) every 1 sec and I have download button which triggers my thread and downloads the file. But still the counter(UI) freezes till the complete file is downloaded and then continues to increment by 2 which I dont know whys its happening.

      I will pasted the whole code down so that u guys can help me figure how to run task independently without waiting for one task.
      I am not expert so there might me logic error or something please feel free to suggest them too.

      Code:
      Project Name : test5
      All Header files

      mythread.h

      #ifndef MYTHREAD_H
      #define MYTHREAD_H
      
      #include <QThread>
      #include <QMutex>
      
      
      class MyThread : public QThread
      {
         Q_OBJECT
      
      public slots:
          void stopRunning();
      
      protected:
         virtual void run();
      
      signals:
      //   void signalValueUpdated(QString);
      
      private:
          bool isRunning;
      
      };
      
      
      
      
      #endif // MYTHREAD_H
      

      qftpfiledownload.h

      #ifndef QFTPFILEDOWNLOAD_H
      #define QFTPFILEDOWNLOAD_H
      
      //HK 29/3/22
      #include<qobject.h>
      #include<QUrl>
      #include<QtNetwork/QNetworkAccessManager>
      #include<QtNetwork/QNetworkRequest>
      #include<QtNetwork/QNetworkReply>
      #include<QEventLoop>
      
      class QftpFileDownload
      {
      public:
      //    QNetworkReply *reply;   //HK 29/3/22
        QftpFileDownload(QString QftpPathName = "",QString QftpUserName = "", QString QftpPassword = "", QString QftpOutputName ="");
      //    QNetworkAccessManager *nam;
      //    QEventLoop loop;
        QString getPathName();
        QString getUserName();
        QString getPassword();
        QString getOutputName();
        void File_Download();
      private:
          QString QftpPathName;   //HK 30/3/22 This requires full path with textfile name eg ."ftp://169.254.10.102/test.txt"
          QString QftpUserName;
          QString QftpPassword;
          QString QftpOutputName;
      
      
      
      };
      
      #endif // QFTPFILEDOWNLOAD_H
      
      

      test5.h

      #ifndef TEST5_H
      #define TEST5_H
      
      #include <QMainWindow>
      #include<QString>
      #include<QTimer>
      #include"mythread.h"
      
      namespace Ui {
      class test5;
      }
      
      class test5 : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit test5(QWidget *parent = 0);
          ~test5();
       unsigned int counter = 0;
          void display_time();
      
      private slots:
          void on_pushButton_clicked();
          void updateTimer();
      signals:
          void download_button_clicked();
      
      private:
          Ui::test5 *ui;
          QTimer *Timer;
          MyThread thread;
      };
      
      #endif // TEST5_H
      
      

      All source files

      main.cpp

      #include "test5.h"
      #include <QApplication>
      #include"ui_test5.h"
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          test5 w;
          w.show();
      
      
      
         return a.exec();
      }
      
      

      mythread.cpp

      #include "mythread.h"
      #include <QString>
      #include"qftpfiledownload.h"
      
      void MyThread::run()
      {
          qDebug("Thread id inside run %d",*((int*)QThread::currentThreadId()));
      
         
          isRunning = 1;
          QftpFileDownload object("ftp://169.254.10.102/test_100mb.txt","Administrator","Nopass123","Mytesting100.txt");
      
          object.File_Download();
      
      
      
      }
      
      void MyThread::stopRunning()
      {
          isRunning = 0;
      }
      
      

      qftpfiledownload.cpp

      #include "qftpfiledownload.h"
      //HK 29/3/22
      #include<QUrl>
      #include<QtNetwork/QNetworkAccessManager>
      #include<QtNetwork/QNetworkRequest>
      #include<QtNetwork/QNetworkReply>
      #include<QEventLoop>
      #include<QFile>
      
      #include"test5.h"
      
      
      
      QftpFileDownload::QftpFileDownload(QString QftpPathName, QString QftpUserName, QString QftpPassword, QString QftpOutputName)
      {
          this->QftpPathName = QftpPathName;
          this->QftpUserName = QftpUserName;
          this->QftpPassword = QftpPassword;
          this->QftpOutputName = QftpOutputName;
      }
      
      QString QftpFileDownload::getPathName()
      {
          return QftpPathName;
      }
      
      QString QftpFileDownload::getUserName()
      {
          return QftpUserName;
      }
      
      QString QftpFileDownload::getPassword()
      {
          return QftpPassword;
      }
      
      QString QftpFileDownload::getOutputName()
      {
          return QftpOutputName;
      }
      
      void QftpFileDownload::File_Download()
      {
          QEventLoop loop;
      
       QNetworkAccessManager *nam = new QNetworkAccessManager();
       QObject::connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
      qDebug()<<"Inside Function";
      test5 time;
      time.display_time();
      //    QUrl url2("ftp://169.254.10.102/test.txt");
       QUrl url2(QftpPathName);
      //      url2.setPassword("Nopass123");
      //      url2.setUserName("Administrator");
       url2.setPassword(QftpPassword);
       url2.setUserName(QftpUserName);
        QNetworkRequest req(url2);
        QNetworkReply *reply = nam->get(req);
        loop.exec();
      
        QFile file(QftpOutputName);
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out<< reply->readAll();
        file.close();
        reply->deleteLater();
      
        qDebug()<<"Last line";
        time.display_time();
      }
      
      

      test5.cpp

      #include "test5.h"
      #include "ui_test5.h"
      #include"qftpfiledownload.h"
      #include"time.h"
      //#include"mythread.h"
      
      test5::test5(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::test5)
      {
          ui->setupUi(this);
      
          Timer = new QTimer();
          connect(Timer,SIGNAL(timeout()),this,SLOT(updateTimer()));
          Timer->start(1000);
          qDebug("Thread id %d",*((int*)QThread::currentThreadId()));
      
          //When the start button is pressed, invoke the start() method in the counter thread
          QObject::connect(this,SIGNAL(download_button_clicked()),&thread,SLOT(start()), Qt::QueuedConnection);
      
          //When the stop button is pressed, invoke the stop() method in the counter thread
          //QObject::connect(stopButton,SIGNAL(clicked()),&thread,SLOT(stopRunning()), Qt::QueuedConnection);
      
          //When the counter thread emits a signal saying its value has been updated, reflect that change in the lineEdit field.
          //QObject::connect(&thread,SIGNAL(signalValueUpdated(const QString&)),lineEdit,SLOT(setText(const QString&)), Qt::QueuedConnection);
      
      //    if(counter % 1000 == 0)
      //    {
      //        ui->Counter->setText(QString(counter));
      //        counter =0;
      //    }
      }
      
      test5::~test5()
      {
          delete ui;
      }
      
      void test5::on_pushButton_clicked()
      {
      //    QftpFileDownload object("ftp://169.254.10.102/test_100mb.txt","Administrator","Nopass123","Mytesting100.txt");
      
      //    object.File_Download();
          emit download_button_clicked();
      }
      
      void test5::updateTimer()
      {
          static unsigned int Counter=0;
      
          ui->Counter->setText(QString::number(Counter));
          Counter++;
      }
      
      void test5::display_time()
      {
          time_t rawtime;
          struct tm * timeinfo;
          time(&rawtime);
          timeinfo = localtime( &rawtime);
          qDebug("%02d:%02d:%02d\n",timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
      //	char output[8];
      //	sprintf(output,"%02d:%02d:%02d",timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
      //	printf("%s\t",output);
      //	printf("%d\n",sizeof(output));
      
      
      }
      
      

      test5.ui
      test5_UI.png

      I will paste the pro file too so that u guys can copy this and workout on this project

      test5.pro

      #-------------------------------------------------
      #
      # Project created by QtCreator 2022-03-31T10:12:10
      #
      #-------------------------------------------------
      
      QT       += core gui network
      
      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
      
      TARGET = test5
      TEMPLATE = app
      
      # The following define makes your compiler emit warnings if you use
      # any feature of Qt which has been marked as deprecated (the exact warnings
      # depend on your compiler). Please consult the documentation of the
      # deprecated API in order to know how to port your code away from it.
      DEFINES += QT_DEPRECATED_WARNINGS
      
      # You can also make your code fail to compile if you use deprecated APIs.
      # In order to do so, uncomment the following line.
      # You can also select to disable deprecated APIs only up to a certain version of Qt.
      #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
      
      
      SOURCES += \
              main.cpp \
              test5.cpp \
          qftpfiledownload.cpp \
          mythread.cpp
      
      HEADERS += \
              test5.h \
          qftpfiledownload.h \
          mythread.h
      
      FORMS += \
              test5.ui
      
      

      Thanks in advance

      P Offline
      P Offline
      Pl45m4
      wrote on 31 Mar 2022, 13:17 last edited by
      #2

      @HimanshuKaushik

      In first place, why you need to have threads at all?
      QNetworkAccessManager works asynchronous using signals and slots.


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      H 1 Reply Last reply 31 Mar 2022, 13:56
      3
      • P Pl45m4
        31 Mar 2022, 13:17

        @HimanshuKaushik

        In first place, why you need to have threads at all?
        QNetworkAccessManager works asynchronous using signals and slots.

        H Offline
        H Offline
        HimanshuKaushik
        wrote on 31 Mar 2022, 13:56 last edited by HimanshuKaushik
        #3

        @Pl45m4 oh okay but then why is UI getting freeze while that process is on?? How do I resolve that?

        P 1 Reply Last reply 31 Mar 2022, 14:11
        0
        • H HimanshuKaushik
          31 Mar 2022, 13:56

          @Pl45m4 oh okay but then why is UI getting freeze while that process is on?? How do I resolve that?

          P Offline
          P Offline
          Pl45m4
          wrote on 31 Mar 2022, 14:11 last edited by Pl45m4 4 Jan 2022, 00:18
          #4

          @HimanshuKaushik

          Your whole code / structure is quite confusing. AFAICS there's no need to create a QThread derived class.
          If you want to increment your counter once a download is finished, just connect to the finished signal.

          You could check out this example:

          • https://doc.qt.io/qt-5/qtnetwork-downloadmanager-example.html

          and @VRonin 's reply here:

          • https://forum.qt.io/topic/88097/downloading-file-from-ftp-server/10

          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          2
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on 31 Mar 2022, 17:56 last edited by
            #5

            Hi,

            You have:

            loop.exec();
            

            In your code which will block the execution until the loop exits.

            As you were already told, don't do that.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            H 1 Reply Last reply 1 Apr 2022, 04:56
            1
            • SGaistS SGaist
              31 Mar 2022, 17:56

              Hi,

              You have:

              loop.exec();
              

              In your code which will block the execution until the loop exits.

              As you were already told, don't do that.

              H Offline
              H Offline
              HimanshuKaushik
              wrote on 1 Apr 2022, 04:56 last edited by
              #6

              @SGaist So when I remove that loop event and its

              loop.exec()
              

              . I am not able to download the file at all. I am getting empty file when removing
              loop.exec()

              jsulmJ 1 Reply Last reply 1 Apr 2022, 06:17
              0
              • H HimanshuKaushik
                1 Apr 2022, 04:56

                @SGaist So when I remove that loop event and its

                loop.exec()
                

                . I am not able to download the file at all. I am getting empty file when removing
                loop.exec()

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on 1 Apr 2022, 06:17 last edited by
                #7

                @HimanshuKaushik said in How to run a task(particular function) independently without blocking my normal flow of code.:

                I am getting empty file when removing

                Because you have to do a bit more than just removing loop.exec()!
                You need to write the file when you get all the data.
                Please take a look at available examples, there is even one for downloading data: https://doc.qt.io/qt-5/qtnetwork-downloadmanager-example.html

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1

                2/7

                31 Mar 2022, 13:17

                topic:navigator.unread, 5
                • Login

                • Login or register to search.
                2 out of 7
                • First post
                  2/7
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved