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. stop a loop in object that has been moved to a QThread?
QtWS25 Last Chance

stop a loop in object that has been moved to a QThread?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qthreadloopstopmovetothread
7 Posts 6 Posters 2.6k 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.
  • P Offline
    P Offline
    pauledd
    wrote on 12 Nov 2019, 18:23 last edited by pauledd 11 Dec 2019, 18:29
    #1

    Hi
    I currently write a communication app that needs to continously receive SPI data.
    So I have a mainwindow with a start and stop button. I created a worker class which then contains the SPI communication. To not block the mainwindow I created a QThread and moved the worker class object into it.

    I can start the doWork() process sucessfuly but how to stop such a loop? Sending signals to the worker class seems not to work since I guess the eventloop is blocked as long as the doWork() loop runs. How to solve that?

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include <QWidget>
    #include <QThread>
    class MainWindow : public QWidget
    {
    	Q_OBJECT
    	QThread thread;
    public:
    	explicit MainWindow(QWidget *parent = nullptr);
    	~MainWindow();
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include <QPushButton>
    #include "worker.h"
    #include <QThread>
    MainWindow::MainWindow(QWidget *parent)
    	:QWidget(parent)
    {
    	QPushButton *pbStart = new QPushButton("START LOOP",this);
    	QPushButton *pbStop = new QPushButton("STOP LOOP",this);
    	pbStop->move(0,40);
    
    	Worker *worker = new Worker;
    	worker->moveToThread(&thread);
    
    	connect(&thread, &QThread::finished, worker, &Worker::deleteLater);
    	connect(pbStart, &QPushButton::clicked, worker, &Worker::doWork);
    	thread.start();
    }
    
    MainWindow::~MainWindow()
    {
    	thread.quit();
    	thread.wait();
    }
    

    worker.h

    #ifndef WORKER_H
    #define WORKER_H
    #include <QObject>
    class Worker :public QObject
    {
    	Q_OBJECT
    public:
    	Worker();
    	~Worker();
    
    public slots:
    	void doWork();
    };
    #endif // WORKER_H
    

    worker.cpp

    #include "worker.h"
    
    Worker::Worker(){}
    Worker::~Worker(){}
    
    void Worker::doWork()
    {
    	while(true){
    		// SPI loop communication
    	}
    };
    

    Can you give me some hints how to solve that?

    O 1 Reply Last reply 12 Nov 2019, 18:40
    0
    • P pauledd
      12 Nov 2019, 18:23

      Hi
      I currently write a communication app that needs to continously receive SPI data.
      So I have a mainwindow with a start and stop button. I created a worker class which then contains the SPI communication. To not block the mainwindow I created a QThread and moved the worker class object into it.

      I can start the doWork() process sucessfuly but how to stop such a loop? Sending signals to the worker class seems not to work since I guess the eventloop is blocked as long as the doWork() loop runs. How to solve that?

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      #include <QWidget>
      #include <QThread>
      class MainWindow : public QWidget
      {
      	Q_OBJECT
      	QThread thread;
      public:
      	explicit MainWindow(QWidget *parent = nullptr);
      	~MainWindow();
      };
      #endif // MAINWINDOW_H
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include <QPushButton>
      #include "worker.h"
      #include <QThread>
      MainWindow::MainWindow(QWidget *parent)
      	:QWidget(parent)
      {
      	QPushButton *pbStart = new QPushButton("START LOOP",this);
      	QPushButton *pbStop = new QPushButton("STOP LOOP",this);
      	pbStop->move(0,40);
      
      	Worker *worker = new Worker;
      	worker->moveToThread(&thread);
      
      	connect(&thread, &QThread::finished, worker, &Worker::deleteLater);
      	connect(pbStart, &QPushButton::clicked, worker, &Worker::doWork);
      	thread.start();
      }
      
      MainWindow::~MainWindow()
      {
      	thread.quit();
      	thread.wait();
      }
      

      worker.h

      #ifndef WORKER_H
      #define WORKER_H
      #include <QObject>
      class Worker :public QObject
      {
      	Q_OBJECT
      public:
      	Worker();
      	~Worker();
      
      public slots:
      	void doWork();
      };
      #endif // WORKER_H
      

      worker.cpp

      #include "worker.h"
      
      Worker::Worker(){}
      Worker::~Worker(){}
      
      void Worker::doWork()
      {
      	while(true){
      		// SPI loop communication
      	}
      };
      

      Can you give me some hints how to solve that?

      O Offline
      O Offline
      ODБOï
      wrote on 12 Nov 2019, 18:40 last edited by
      #2

      @pauledd hi,

      take a look on how they use signal/slot to communicate with the worker object https://doc.qt.io/qt-5/qthread.html#details
      and avoid using an infinite loop

      1 Reply Last reply
      2
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 12 Nov 2019, 20:02 last edited by
        #3

        Hi,

        If you want to keep the loop then add a variable to break it.

        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
        1
        • F Offline
          F Offline
          fcarney
          wrote on 12 Nov 2019, 20:38 last edited by
          #4

          @pauledd said in stop a loop in object that has been moved to a QThread?:

          Worker::doWork()

          As shown, at no time is this function checking the Qt Event loop.

          public slots:
              void doWork(){
                  ...
                  while(m_running){
                      // process server
                      UA_Server_run_iterate(m_server, true);
          
                      // process events like signals
                      QCoreApplication::processEvents();
                  }
                  ...
              }
          
              void stopWork(){
                  m_running = false;
              }
          

          There are signals connected to the slots above to control my server.

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0
          • P Offline
            P Offline
            pauledd
            wrote on 13 Nov 2019, 07:54 last edited by
            #5

            thank you for your hints. I go for @fcarney 's solution for now, but I almost surely will have to gather SPI data in bigger chunks too and send them back to the gui for further processing/storing so that the aquisition loop wont be infinite anyway.

            J 1 Reply Last reply 13 Nov 2019, 07:57
            0
            • P pauledd
              13 Nov 2019, 07:54

              thank you for your hints. I go for @fcarney 's solution for now, but I almost surely will have to gather SPI data in bigger chunks too and send them back to the gui for further processing/storing so that the aquisition loop wont be infinite anyway.

              J Online
              J Online
              J.Hilk
              Moderators
              wrote on 13 Nov 2019, 07:57 last edited by
              #6

              @pauledd
              I would actually not recommend that.

              I don't know why people keep on suggesting processEvents, as a legit solution. It drives me up the wall every time I see it.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              1 Reply Last reply
              4
              • M Offline
                M Offline
                MCam
                wrote on 13 Nov 2019, 10:34 last edited by
                #7

                @pauledd
                I would recommend using the build-in QThread mechanism to interrupt a thread:

                public slots:
                    void doWork() {
                        forever() {
                            ...
                            if ( QThread::currentThread()->isInterruptionRequested() ) {
                                        return;
                            }
                            ...
                        }
                    }
                

                You can add this check to your SPI loop multiple times but avoid to call it too often, according to the dokumentation.
                Add something like this to your MainWindow-Instance:

                public slots:
                    void cancel() {
                        if( thread.isRunning()) {
                            thread.requestInterruption();
                        }
                    }
                

                and connect this Slot to some Cancel-Button.

                1 Reply Last reply
                3

                3/7

                12 Nov 2019, 20:02

                • Login

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