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. call functions using QtConcurrent/QFuture
Forum Update on Monday, May 27th 2025

call functions using QtConcurrent/QFuture

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 4 Posters 186 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.
  • B Offline
    B Offline
    Blackzero
    wrote on 24 May 2024, 11:47 last edited by
    #1

    What's the difference when I put the ui caller directly in the thread loop without using emit, will it cause an error one day?

        ui->label->setText("Value : " + QString::number(Counter));
    
        //emit Updategui_signal("Value : " + QString::number(Counter));
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QtConcurrent>
    #include <QDebug>
    #include <QThread>
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    signals:
        void Updategui_signal(QString data);
    
    private slots:
        void Updategui_slot(QString data);
    
    
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        int Counter = 0;
        bool isThread_start = false;
        bool isThread_running = false;
        QFuture<void> myThread;
        void ConcurrentThread();
    };
    #endif // MAINWINDOW_H
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        connect(this, SIGNAL(Updategui_signal(QString)),this,SLOT(Updategui_slot(QString)));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::Updategui_slot(QString data)
    {
        ui->label->setText(data);
    }
    
    void MainWindow::ConcurrentThread()
    {
        while (isThread_running == true)
        {
    
            QThread::msleep(100);
            Counter = Counter + 1;
            
            // call function GUI
            ui->label->setText("Value : " + QString::number(Counter));
    
            //emit Updategui_signal("Value : " + QString::number(Counter));
        }
    }
    
    
    void MainWindow::on_pushButton_clicked()
    {
        if (isThread_start == false)
        {
            isThread_start = true;
            isThread_running = true;
            myThread =  QtConcurrent::run(this,&MainWindow::ConcurrentThread);
            myThread.resume();
    
        }
        else
        {
            isThread_start = false;
            isThread_running = false;
            myThread.pause();
            myThread.cancel();
        }
    }
    
    P K S 3 Replies Last reply 24 May 2024, 11:55
    0
    • B Blackzero
      24 May 2024, 11:47

      What's the difference when I put the ui caller directly in the thread loop without using emit, will it cause an error one day?

          ui->label->setText("Value : " + QString::number(Counter));
      
          //emit Updategui_signal("Value : " + QString::number(Counter));
      

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QtConcurrent>
      #include <QDebug>
      #include <QThread>
      QT_BEGIN_NAMESPACE
      namespace Ui { class MainWindow; }
      QT_END_NAMESPACE
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      signals:
          void Updategui_signal(QString data);
      
      private slots:
          void Updategui_slot(QString data);
      
      
          void on_pushButton_clicked();
      
      private:
          Ui::MainWindow *ui;
          int Counter = 0;
          bool isThread_start = false;
          bool isThread_running = false;
          QFuture<void> myThread;
          void ConcurrentThread();
      };
      #endif // MAINWINDOW_H
      
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          connect(this, SIGNAL(Updategui_signal(QString)),this,SLOT(Updategui_slot(QString)));
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::Updategui_slot(QString data)
      {
          ui->label->setText(data);
      }
      
      void MainWindow::ConcurrentThread()
      {
          while (isThread_running == true)
          {
      
              QThread::msleep(100);
              Counter = Counter + 1;
              
              // call function GUI
              ui->label->setText("Value : " + QString::number(Counter));
      
              //emit Updategui_signal("Value : " + QString::number(Counter));
          }
      }
      
      
      void MainWindow::on_pushButton_clicked()
      {
          if (isThread_start == false)
          {
              isThread_start = true;
              isThread_running = true;
              myThread =  QtConcurrent::run(this,&MainWindow::ConcurrentThread);
              myThread.resume();
      
          }
          else
          {
              isThread_start = false;
              isThread_running = false;
              myThread.pause();
              myThread.cancel();
          }
      }
      
      P Online
      P Online
      Pl45m4
      wrote on 24 May 2024, 11:55 last edited by Pl45m4
      #2

      @Blackzero said in call functions using QtConcurrent/QFuture:

      What's the difference when I put the ui caller directly in the thread loop without using emit, will it cause an error one day?

      ui->label->setText("Value : " + QString::number(Counter));
      
      //emit Updategui_signal("Value : " + QString::number(Counter));
      

      Don't access the GUI directly from another thread.
      Using a signal to send/receive notifications or get/set values is better.

      connect(this, SIGNAL(Updategui_signal(QString)),this,SLOT(Updategui_slot(QString)));

      Do yourself a favor and learn/use the function pointer based connection style.

      Edit:

      Btw. your code includes a lot of redundant and unnecessary stuff...

      myThread =  QtConcurrent::run(this,&MainWindow::ConcurrentThread);
      myThread.resume(); // does not work with QtConcurrent::run
      

      Resumes the asynchronous computation represented by the future(). This is a convenience method that simply calls setSuspended(false).
      (https://doc.qt.io/qt-6/qfuture.html#resume)

      And:
      Be aware that not all computations can be suspended. For example, the QFuture returned by QtConcurrent::run() cannot be suspended; but the QFuture returned by QtConcurrent::mappedReduced() can.
      ( https://doc.qt.io/qt-6/qfuture.html#setSuspended)

      bool isThread_start = false;
      bool isThread_running = false;
      

      One of them also not needed since you use them for the same purpose and set both of them true / false at the same time.
      And since you cannot pause your QtConcurrent::run anyway, there is no point of having two boolean variables to check whether your task was started and if it's running or was stopped/paused.
      Even if it would work or is needed in your case, you still have these two to get the state of your QFuture thread at any time:

      bool QFuture::isRunning() const
      Returns true if the asynchronous computation represented by this future is currently running; otherwise returns false.

      bool QFuture::isStarted() const
      Returns true if the asynchronous computation represented by this future has been started; otherwise returns false.


      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
      • B Blackzero
        24 May 2024, 11:47

        What's the difference when I put the ui caller directly in the thread loop without using emit, will it cause an error one day?

            ui->label->setText("Value : " + QString::number(Counter));
        
            //emit Updategui_signal("Value : " + QString::number(Counter));
        

        mainwindow.h

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include <QtConcurrent>
        #include <QDebug>
        #include <QThread>
        QT_BEGIN_NAMESPACE
        namespace Ui { class MainWindow; }
        QT_END_NAMESPACE
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            MainWindow(QWidget *parent = nullptr);
            ~MainWindow();
        
        signals:
            void Updategui_signal(QString data);
        
        private slots:
            void Updategui_slot(QString data);
        
        
            void on_pushButton_clicked();
        
        private:
            Ui::MainWindow *ui;
            int Counter = 0;
            bool isThread_start = false;
            bool isThread_running = false;
            QFuture<void> myThread;
            void ConcurrentThread();
        };
        #endif // MAINWINDOW_H
        
        

        mainwindow.cpp

        #include "mainwindow.h"
        #include "ui_mainwindow.h"
        
        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
            , ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
            connect(this, SIGNAL(Updategui_signal(QString)),this,SLOT(Updategui_slot(QString)));
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        
        void MainWindow::Updategui_slot(QString data)
        {
            ui->label->setText(data);
        }
        
        void MainWindow::ConcurrentThread()
        {
            while (isThread_running == true)
            {
        
                QThread::msleep(100);
                Counter = Counter + 1;
                
                // call function GUI
                ui->label->setText("Value : " + QString::number(Counter));
        
                //emit Updategui_signal("Value : " + QString::number(Counter));
            }
        }
        
        
        void MainWindow::on_pushButton_clicked()
        {
            if (isThread_start == false)
            {
                isThread_start = true;
                isThread_running = true;
                myThread =  QtConcurrent::run(this,&MainWindow::ConcurrentThread);
                myThread.resume();
        
            }
            else
            {
                isThread_start = false;
                isThread_running = false;
                myThread.pause();
                myThread.cancel();
            }
        }
        
        K Offline
        K Offline
        Ketan__Patel__0011
        wrote on 24 May 2024, 13:23 last edited by
        #3

        @Blackzero
        As my personal experience don't dare to update GUI control Directly in therad and never block the thread by update the control in thread.

        you will get may kind of problem when you update GUI control Directly in therad like GUI Frezzing, control may not update sometime, also you will lost the stylesheet of your control in some cases.

        @Pl45m4 said in call functions using QtConcurrent/QFuture:

        Using a signal to send/receive notifications or get/set values is better.

        this is the correct way to update GUI control by using signal and slot functionality.

        1 Reply Last reply
        0
        • B Blackzero
          24 May 2024, 11:47

          What's the difference when I put the ui caller directly in the thread loop without using emit, will it cause an error one day?

              ui->label->setText("Value : " + QString::number(Counter));
          
              //emit Updategui_signal("Value : " + QString::number(Counter));
          

          mainwindow.h

          #ifndef MAINWINDOW_H
          #define MAINWINDOW_H
          
          #include <QMainWindow>
          #include <QtConcurrent>
          #include <QDebug>
          #include <QThread>
          QT_BEGIN_NAMESPACE
          namespace Ui { class MainWindow; }
          QT_END_NAMESPACE
          
          class MainWindow : public QMainWindow
          {
              Q_OBJECT
          
          public:
              MainWindow(QWidget *parent = nullptr);
              ~MainWindow();
          
          signals:
              void Updategui_signal(QString data);
          
          private slots:
              void Updategui_slot(QString data);
          
          
              void on_pushButton_clicked();
          
          private:
              Ui::MainWindow *ui;
              int Counter = 0;
              bool isThread_start = false;
              bool isThread_running = false;
              QFuture<void> myThread;
              void ConcurrentThread();
          };
          #endif // MAINWINDOW_H
          
          

          mainwindow.cpp

          #include "mainwindow.h"
          #include "ui_mainwindow.h"
          
          MainWindow::MainWindow(QWidget *parent)
              : QMainWindow(parent)
              , ui(new Ui::MainWindow)
          {
              ui->setupUi(this);
              connect(this, SIGNAL(Updategui_signal(QString)),this,SLOT(Updategui_slot(QString)));
          }
          
          MainWindow::~MainWindow()
          {
              delete ui;
          }
          
          void MainWindow::Updategui_slot(QString data)
          {
              ui->label->setText(data);
          }
          
          void MainWindow::ConcurrentThread()
          {
              while (isThread_running == true)
              {
          
                  QThread::msleep(100);
                  Counter = Counter + 1;
                  
                  // call function GUI
                  ui->label->setText("Value : " + QString::number(Counter));
          
                  //emit Updategui_signal("Value : " + QString::number(Counter));
              }
          }
          
          
          void MainWindow::on_pushButton_clicked()
          {
              if (isThread_start == false)
              {
                  isThread_start = true;
                  isThread_running = true;
                  myThread =  QtConcurrent::run(this,&MainWindow::ConcurrentThread);
                  myThread.resume();
          
              }
              else
              {
                  isThread_start = false;
                  isThread_running = false;
                  myThread.pause();
                  myThread.cancel();
              }
          }
          
          S Offline
          S Offline
          SimonSchroeder
          wrote on 27 May 2024, 06:54 last edited by
          #4

          @Blackzero said in call functions using QtConcurrent/QFuture:

          ui->label->setText("Value : " + QString::number(Counter));

          This will crash eventually because it is not running inside the GUI thread. What you could do instead is QMetaObject::invokeMethod(qApp, [this]() { ui->label->setText("Value:" + QString::number(Counter); });. Having a signal instead to call is much better. The signal will automatically detect that the slot is located in a different thread and will dispatch it to the other thread accordingly. Using signals/slots makes multi-threading a lot easier.

          If you really want to wait for 100ms you should use a timer. In a lot of cases this is even sufficient and you'll not need a separate thread for that. If you really need a thread (because you want to do a lot more stuff in addition what you have showed), just start a plain old QThread. It will have its own event queue running and thus can serve QTimers. Usually, you should use worker objects in this context. However, you also need to start the timer inside the thread. So, I personally would just use lambdas without a worker object:

          QMetaObject::invokeMethod(QAbstractEventDispatcher::instance(thread), [this]() 
          {
            m_timer = new QTimer(m_thread);
            QObject::connect(m_timer, &QTimer::timeout, QAbstractEventDispatcher::instance(thread),
                             [this]() { Counter = Counter + 1; QMetaObject::invokeMethod(qApp, [this]() { ui->label->setText("Value:" + QString::number(Counter); }); });
            m_timer->start(100);
          }
          

          QMetaObject::invokeMethod is like manually placing a slot call into an event queue. Notice that connect needs a context object inside the correct thread (maybe it would even work without the context object because the timeout will happen inside the correct thread).

          1 Reply Last reply
          0

          1/4

          24 May 2024, 11:47

          • Login

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