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. QT thread not syncing

QT thread not syncing

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 584 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.
  • S Offline
    S Offline
    sigmind
    wrote on last edited by sigmind
    #1

    I am working on a project for passing argument and return the values in between thread. So far I have tried:

    mainwindow.cpp (slightly updated)

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // The thread and the worker are created in the constructor so it is always safe to delete them.
        thread = new QThread();
        worker = new Worker();
    
        worker->moveToThread(thread);
        connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(addNewImage(QString)));
        connect(worker, SIGNAL(workRequested()), thread, SLOT(start()));
       // connect(thread, SIGNAL(started()), worker, SLOT(doWork(int)));
        connect(this, SIGNAL(requestUpdate(int)), worker, SLOT(doWork(int)));
        connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection);
    }
    
    MainWindow::~MainWindow()
    {
        worker->abort();
        thread->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread;
        delete worker;
    
        delete ui;
    }
    
    void MainWindow::on_startButton_clicked()
    {
     int i=0;
    for(i=0;i<5;i++)   // Run 5 times
    {
        // To avoid having two threads running simultaneously, the previous thread is aborted.
        worker->abort();
        thread->wait(); // If the thread is not running, this will immediately return.
        int enc = 5;
        //worker->requestWork();
        emit requestUpdate(enc);
    }
    }
    void MainWindow::addNewImage(QString enc)
    {
       qDebug(qUtf8Printable(enc));
    }
    

    mainwindow.h

    
    
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThread>
    #include "worker.h"
    
    namespace Ui
    {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        /**
         * @brief Thread object which will let us manipulate the running thread
         */
        QThread *thread;
        /**
         * @brief Object which contains methods that should be runned in another thread
         */
        Worker *worker;
    
    private slots:
        void on_startButton_clicked();
    public slots:
       void addNewImage(QString enc);
    signals:
        void requestUpdate(int initial);
    
    };
    
    #endif // MAINWINDOW_H
    
    

    and worker.cpp

    
    #include "worker.h"
    #include <QTimer>
    #include <QEventLoop>
    
    #include <QThread>
    #include <QDebug>
    
    Worker::Worker(QObject *parent) :
        QObject(parent)
    {
        _working =false;
        _abort = false;
    }
    
    void Worker::requestWork()
    {
        mutex.lock();
        _working = true;
        _abort = false;
        qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
        mutex.unlock();
    
        emit workRequested();
    }
    
    void Worker::abort()
    {
        mutex.lock();
        if (_working) {
            _abort = true;
            qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
        }
        mutex.unlock();
    }
    
    void Worker::doWork(int initial)
    {
        qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
    
            // Checks if the process should be aborted
            mutex.lock();
            bool abort = _abort;
            mutex.unlock();
    
    
        
    QString value = "External API call";
         
            emit valueChanged(value);
        }
    
        // Set _working to false, meaning the process can't be aborted anymore.
        mutex.lock();
        _working = false;
        mutex.unlock();
    
        qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
    
        //Once 60 sec passed, the finished signal is sent
        emit finished();
    }
    
    

    worker.h

    
    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QObject>
    #include <QMutex>
    
    class Worker : public QObject
    {
        Q_OBJECT
    
    public:
        explicit Worker(QObject *parent = 0);
        /**
         * @brief Requests the process to start
         *
         * It is thread safe as it uses #mutex to protect access to #_working variable.
         */
        void requestWork();
        /**
         * @brief Requests the process to abort
         *
         * It is thread safe as it uses #mutex to protect access to #_abort variable.
         */
        void abort();
    
    private:
        /**
         * @brief Process is aborted when @em true
         */
        bool _abort;
        /**
         * @brief @em true when Worker is doing work
         */
        bool _working;
        /**
         * @brief Protects access to #_abort
         */
        QMutex mutex;
    
    signals:
        /**
         * @brief This signal is emitted when the Worker request to Work
         * @sa requestWork()
         */
        void workRequested();
        /**
         * @brief This signal is emitted when counted value is changed (every sec)
         */
        void valueChanged(const QString &value);
        /**
         * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
         */
        void finished();
    
    public slots:
        /**
         * @brief Does something
         *
         * Counts 60 sec in this example.
         * Counting is interrupted if #_aborted is set to true.
         */
        void doWork(int initial);
    };
    
    #endif // WORKER_H
    
    

    The program compiles fine but while running, it gives

    QObject::connect: No such signal QThread::requestUpdate(int)
    

    The program is expected to execute the worker thread each time being invoked from mainWindow.cpp. But the program outputs:

    Request worker start in Thread  0x7f0431575740
    Request worker aborting in Thread  0x7f0431575740
    Starting worker process in Thread  0x7f04252e5700
    Worker process finished in Thread  0x7f04252e5700
    Request worker start in Thread  0x7f0431575740
    Request worker aborting in Thread  0x7f0431575740
    Starting worker process in Thread  0x7f04252e5700
    Worker process finished in Thread  0x7f04252e5700
    Request worker start in Thread  0x7f0431575740
    Request worker aborting in Thread  0x7f0431575740
    Starting worker process in Thread  0x7f04252e5700
    Worker process finished in Thread  0x7f04252e5700
    Request worker start in Thread  0x7f0431575740
    Request worker aborting in Thread  0x7f0431575740
    Starting worker process in Thread  0x7f04252e5700
    Worker process finished in Thread  0x7f04252e5700
    Request worker start in Thread  0x7f0431575740
    Request worker aborting in Thread  0x7f0431575740
    Starting worker process in Thread  0x7f04252e5700
    Worker process finished in Thread  0x7f04252e5700
    Request worker start in Thread  0x7f0431575740
    External API call
    External API call
    External API call
    External API call
    External API call
    Starting worker process in Thread  0x7f0424ae4700
    Worker process finished in Thread  0x7f0424ae4700
    External API call
    

    Where the qDebug prints "External API call" 5 times after finishing thread executions, but is expected to print parallel. What might go wrong here?

    SGaistS 1 Reply Last reply
    0
    • S sigmind

      I am working on a project for passing argument and return the values in between thread. So far I have tried:

      mainwindow.cpp (slightly updated)

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      #include <QDebug>
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      
          // The thread and the worker are created in the constructor so it is always safe to delete them.
          thread = new QThread();
          worker = new Worker();
      
          worker->moveToThread(thread);
          connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(addNewImage(QString)));
          connect(worker, SIGNAL(workRequested()), thread, SLOT(start()));
         // connect(thread, SIGNAL(started()), worker, SLOT(doWork(int)));
          connect(this, SIGNAL(requestUpdate(int)), worker, SLOT(doWork(int)));
          connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection);
      }
      
      MainWindow::~MainWindow()
      {
          worker->abort();
          thread->wait();
          qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
          delete thread;
          delete worker;
      
          delete ui;
      }
      
      void MainWindow::on_startButton_clicked()
      {
       int i=0;
      for(i=0;i<5;i++)   // Run 5 times
      {
          // To avoid having two threads running simultaneously, the previous thread is aborted.
          worker->abort();
          thread->wait(); // If the thread is not running, this will immediately return.
          int enc = 5;
          //worker->requestWork();
          emit requestUpdate(enc);
      }
      }
      void MainWindow::addNewImage(QString enc)
      {
         qDebug(qUtf8Printable(enc));
      }
      

      mainwindow.h

      
      
      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QThread>
      #include "worker.h"
      
      namespace Ui
      {
      class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
          /**
           * @brief Thread object which will let us manipulate the running thread
           */
          QThread *thread;
          /**
           * @brief Object which contains methods that should be runned in another thread
           */
          Worker *worker;
      
      private slots:
          void on_startButton_clicked();
      public slots:
         void addNewImage(QString enc);
      signals:
          void requestUpdate(int initial);
      
      };
      
      #endif // MAINWINDOW_H
      
      

      and worker.cpp

      
      #include "worker.h"
      #include <QTimer>
      #include <QEventLoop>
      
      #include <QThread>
      #include <QDebug>
      
      Worker::Worker(QObject *parent) :
          QObject(parent)
      {
          _working =false;
          _abort = false;
      }
      
      void Worker::requestWork()
      {
          mutex.lock();
          _working = true;
          _abort = false;
          qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
          mutex.unlock();
      
          emit workRequested();
      }
      
      void Worker::abort()
      {
          mutex.lock();
          if (_working) {
              _abort = true;
              qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
          }
          mutex.unlock();
      }
      
      void Worker::doWork(int initial)
      {
          qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
      
              // Checks if the process should be aborted
              mutex.lock();
              bool abort = _abort;
              mutex.unlock();
      
      
          
      QString value = "External API call";
           
              emit valueChanged(value);
          }
      
          // Set _working to false, meaning the process can't be aborted anymore.
          mutex.lock();
          _working = false;
          mutex.unlock();
      
          qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
      
          //Once 60 sec passed, the finished signal is sent
          emit finished();
      }
      
      

      worker.h

      
      #ifndef WORKER_H
      #define WORKER_H
      
      #include <QObject>
      #include <QMutex>
      
      class Worker : public QObject
      {
          Q_OBJECT
      
      public:
          explicit Worker(QObject *parent = 0);
          /**
           * @brief Requests the process to start
           *
           * It is thread safe as it uses #mutex to protect access to #_working variable.
           */
          void requestWork();
          /**
           * @brief Requests the process to abort
           *
           * It is thread safe as it uses #mutex to protect access to #_abort variable.
           */
          void abort();
      
      private:
          /**
           * @brief Process is aborted when @em true
           */
          bool _abort;
          /**
           * @brief @em true when Worker is doing work
           */
          bool _working;
          /**
           * @brief Protects access to #_abort
           */
          QMutex mutex;
      
      signals:
          /**
           * @brief This signal is emitted when the Worker request to Work
           * @sa requestWork()
           */
          void workRequested();
          /**
           * @brief This signal is emitted when counted value is changed (every sec)
           */
          void valueChanged(const QString &value);
          /**
           * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
           */
          void finished();
      
      public slots:
          /**
           * @brief Does something
           *
           * Counts 60 sec in this example.
           * Counting is interrupted if #_aborted is set to true.
           */
          void doWork(int initial);
      };
      
      #endif // WORKER_H
      
      

      The program compiles fine but while running, it gives

      QObject::connect: No such signal QThread::requestUpdate(int)
      

      The program is expected to execute the worker thread each time being invoked from mainWindow.cpp. But the program outputs:

      Request worker start in Thread  0x7f0431575740
      Request worker aborting in Thread  0x7f0431575740
      Starting worker process in Thread  0x7f04252e5700
      Worker process finished in Thread  0x7f04252e5700
      Request worker start in Thread  0x7f0431575740
      Request worker aborting in Thread  0x7f0431575740
      Starting worker process in Thread  0x7f04252e5700
      Worker process finished in Thread  0x7f04252e5700
      Request worker start in Thread  0x7f0431575740
      Request worker aborting in Thread  0x7f0431575740
      Starting worker process in Thread  0x7f04252e5700
      Worker process finished in Thread  0x7f04252e5700
      Request worker start in Thread  0x7f0431575740
      Request worker aborting in Thread  0x7f0431575740
      Starting worker process in Thread  0x7f04252e5700
      Worker process finished in Thread  0x7f04252e5700
      Request worker start in Thread  0x7f0431575740
      Request worker aborting in Thread  0x7f0431575740
      Starting worker process in Thread  0x7f04252e5700
      Worker process finished in Thread  0x7f04252e5700
      Request worker start in Thread  0x7f0431575740
      External API call
      External API call
      External API call
      External API call
      External API call
      Starting worker process in Thread  0x7f0424ae4700
      Worker process finished in Thread  0x7f0424ae4700
      External API call
      

      Where the qDebug prints "External API call" 5 times after finishing thread executions, but is expected to print parallel. What might go wrong here?

      SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi

      @sigmind said in QT thread not syncing:

      or(i=0;i<5;i++) // Run 5 times
      {
      // To avoid having two threads running simultaneously, the previous thread is aborted.
      worker->abort();
      thread->wait(); // If the thread is not running, this will immediately return.
      int enc = 5;
      //worker->requestWork();
      emit requestUpdate(enc);
      }

      You are aborting your thread and then waiting on it to finish, therefore the output you get is correct. If you want to parallelise things, you'll have to start several threads in parallel.

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

      1 Reply Last reply
      3
      • S Offline
        S Offline
        sigmind
        wrote on last edited by
        #3

        @SGaist Thanks for pointing out. Modifying it like:

        or(i=0;i<5;i++) // Run 5 times
        {
        // To avoid having two threads running simultaneously, the previous thread is aborted.
        //worker->abort();
        //thread->wait(); // If the thread is not running, this will immediately return.
        int enc = 5;
        worker->requestWork();
        emit requestUpdate(enc);
        }
        

        returns result like this:

        Request worker start in Thread  0x7f083eb3d740
        Request worker start in Thread  0x7f083eb3d740
        Request worker start in Thread  0x7f083eb3d740
        Request worker start in Thread  0x7f083eb3d740
        Request worker start in Thread  0x7f083eb3d740
        Request worker start in Thread  0x7f083eb3d740
        Starting worker process in Thread  0x7f082c93a700
        Worker process finished in Thread  0x7f082c93a700
        Starting worker process in Thread  0x7f082c93a700
        Worker process finished in Thread  0x7f082c93a700
        Starting worker process in Thread  0x7f082c93a700
        Worker process finished in Thread  0x7f082c93a700
        Starting worker process in Thread  0x7f082c93a700
        Worker process finished in Thread  0x7f082c93a700
        External API call
        Starting worker process in Thread  0x7f082c93a700
        External API call
        External API call
        Worker process finished in Thread  0x7f082c93a700
        Starting worker process in Thread  0x7f082c93a700
        External API call
        Worker process finished in Thread  0x7f082c93a700
        External API call
        External API call
        

        Is it true that the "worker thread" is working parallely? Or should I do something more to run it parallel and synchronously? Thanks in advance.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Re-reading your code, your worker object looks a bit convoluted.

          The most simple version is:

          • Create a QThread object
          • Create your worker object
          • Move it to your QThread object
          • Connect QThread's started signal to your worker object's doWork slot
          • Configure your worker with the parameters you want
          • Call QThread's start method

          In any case, can you explain exactly what you want to do ? Depending on that, maybe QtConcurrent might be a better choice.

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

          1 Reply Last reply
          5
          • S Offline
            S Offline
            sigmind
            wrote on last edited by
            #5

            I am trying to call external API in parallel with main thread so that the main thread will not wait for the completion of slow API call rather queue the result later.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              What kind of API is that ?

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

              1 Reply Last reply
              0

              • Login

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