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. main and background thread example
Forum Updated to NodeBB v4.3 + New Features

main and background thread example

Scheduled Pinned Locked Moved Unsolved General and Desktop
20 Posts 3 Posters 8.1k Views 2 Watching
  • 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.
  • U Offline
    U Offline
    user4592357
    wrote on last edited by
    #5

    i'll try using QTimer instead of this_thread::sleep_for(). but it still blows my mind how my previous implementation worked the way i wanted with this code.

    and is everything else okay with this code (i.e. the use of atomic bool etc.)?

    1 Reply Last reply
    0
    • U Offline
      U Offline
      user4592357
      wrote on last edited by
      #6

      i can't figure out how to do that. this is what i have right now:

      #include <QtWidgets/QMainWindow>
      #include <QApplication>
      #include <QObject>
      #include <QThread>
      #include <iostream>
      #include <thread>
      #include <QtWidgets/QLabel>
      #include <atomic>
      #include <QTimer>
      
      std::atomic<bool> bMainThreadRunning { true };
      
      class ThreadObj : public QObject {
      public:
      	ThreadObj() : counter(0) {}
      	void work() {
      		auto timer = new QTimer;
      		//timer.setInterval(3000);
      		connect(timer, &QTimer::timeout, this, &ThreadObj::inc);
      		timer->start(3000);
      	}
      	void inc() { 
      		while(bMainThreadRunning)
      			++counter;
      	}
      private:
      	int counter { 0 };
      };
      
      class Obj {
      public:
      	void start() {
      		ThreadObj obj;
      		m_thread = std::thread(&ThreadObj::work, &obj);
      	}
      	void onMainThreadFinished() {
      		bMainThreadRunning = false;
      		m_thread.join();
      	}
      private:
      	std::thread m_thread;
      };
      
      int main(int argc, char *argv[]) {
      	QApplication a(argc, argv);
      	Obj o;
      	o.start();
      
      	QWidget w;
      	w.show();
      
      	auto ret = a.exec();
      	o.onMainThreadFinished();
      
      	return 0;
      }
      
      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #7

        You forgot you used a std::thread. Why not use QThread since you are using Qt and a worker object ?

        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
        • U Offline
          U Offline
          user4592357
          wrote on last edited by user4592357
          #8

          i did that. what i need is, when in background thread something weird happens, i tell the main thread to show a message box. then if at some time the "good" state of background thread is restored, main thread closes the message box.

          here's what i have now. actually the application works. but at some points it crashes. looking at the crash log i can say that the reason is the background thread but i don't see how my implementation is wrong. i appended the crash log after code.

          class BgThread : public QThread {
          	Q_OBJECT
          public:
          	explicit BgThread (const int &nSeconds, QObject *parent = nullptr) : QThread(parent), interval(1000 * nSeconds) /* to milliseconds */  {}
          
          	void onStopBgThread() { running = false; }
          
          signals:
          	void somethingWentWrong();
                  void restoreGoodState();
          
          private slots:
          	void performWork() {
                       if(/* something went wrong */) {
          		emit somethingWentWrong();
          		good_state = false;
          	     } else if(!good_state) { // means going from bad state to good state
          		emit restoreGoodState();
          		good_state = true;
          	     }
                  }
          
          private:
          	void run() override {
                      QTimer timer;
          	    connect(&timer, SIGNAL(timeout()), this, SLOT(performWork()), Qt::DirectConnection);
          	    timer.start(interval);
          
                      exec();
                      quit();
                      wait();
                  }
          
          private:
          	int interval;
                  bool running { true };
                  bool good_state { true };
          };
          
          class MainApp {
          public:
              void start_bg_thread(const int seconds) {
                 	thread = new BgThread { seconds, this };
                  connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
          	connect(thread, SIGNAL(somethingWentWrong()), SLOT(onSomethingWentWrong()));
                  connect(thread, SIGNAL(restoreGoodState()), SLOT(onRestoreGoodState()));
          	thread->start();
              }
          
              void stop_bg_thread() {
          	thread->onStopBgThread();
              }
          
          public slots:
              void onSomethingWentWrong() {
          	if(!msgBox) {
          		msgBox= new QMessageBox(window());
          		msgBox->setIcon(QMessageBox::Warning);
          		msgBox->setWindowTitle("window title");
          		msgBox->setText("message box text");
          		const auto pExitBtn = msgBox->addButton(tr("Exit"), QMessageBox::AcceptRole);
          		connect(pExitBtn, SIGNAL(clicked()), qApp, SLOT(quit()));
          	}
          	msgBox->exec();	
              }
          
              void onRestoreGoodState() {
          	msgBox->close();
              }
          private:
              BgThread *thread { nullptr };
              QMessageBox *msgBox;
          };
          

          this is basically it. and somewhere in the app init process i call

          MainApp app;
          app.start_bg_thread(5);
          

          the crash log is something like this (stacktrace):

          do_system () from /lib64/libc.so.6
          system () from /lib64/libc.so.6
          // call signal handler
          ...
          pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
          QThread::msleep(unsigned long) ()
          start_thread () from /lib64/libpthread.so.0
          clone () from /lib64/libc.so.6
          waitpid () from /lib64/libc.so.6
          do_system () from /lib64/libc.so.6
          system () from /lib64/libc.so.6
          // call signal handler
          BgThread::onStopBgThread ()
          MainApp::qt_metacall(QMetaObject::Call, int, void**) ()
          QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
          QCoreApplication::exec()
          main ()
          
          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #9

            Did you check the memory used by you application ?

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

            U 1 Reply Last reply
            0
            • SGaistS SGaist

              Did you check the memory used by you application ?

              U Offline
              U Offline
              user4592357
              wrote on last edited by user4592357
              #10

              @SGaist

              what do you mean by check? and no, how should i?

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

                Using the top command for example. Valgrind etc.

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

                U 1 Reply Last reply
                1
                • SGaistS SGaist

                  Using the top command for example. Valgrind etc.

                  U Offline
                  U Offline
                  user4592357
                  wrote on last edited by
                  #12

                  @SGaist

                  okay, thanks.
                  one last question, as you can see, on timer's timeout i execute a function. is it possible stop the timer (so the function won't be executed), and then restart it again?

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

                    Yes:
                    QTimer::stop
                    QTimer::start

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

                    U 1 Reply Last reply
                    3
                    • SGaistS SGaist

                      Yes:
                      QTimer::stop
                      QTimer::start

                      U Offline
                      U Offline
                      user4592357
                      wrote on last edited by
                      #14

                      @SGaist

                      hi again,
                      i ran valgrind and it says there's a memory leak on exec() which is in run() overridden method. so what's wrong?

                      1 Reply Last reply
                      0
                      • U user4592357

                        i wanna write a basic thread example. here's the idea:
                        i have the main event loop. before calling app.exec(), i create an object which itself creates an object and puts it in a separate thread for running. i need some way to tell the background thread that main thread has finished (to join()), so i have a bool to indicate that.

                        however, when the application exits, something goes wrong. i'm running it using visual studio and the debugging session won't stop. i don't understand what's wrong. here's the code:

                        #include <QApplication>
                        #include <QObject>
                        #include <QThread>
                        #include <iostream>
                        #include <thread>
                        #include <QtWidgets/QLabel>
                        #include <atomic>
                        
                        std::atomic<bool> bMainThreadRunning { true };
                        
                        class ThreadObj {
                        public:
                        	void work() {
                        		while(bMainThreadRunning) {
                        			++counter;
                        			std::this_thread::sleep_for(std::chrono::seconds(5));
                        		}
                        	}
                        private:
                        	int counter { 0 };
                        };
                        
                        class Obj {
                        public:
                        	void start() {
                        		ThreadObj obj;
                        		m_thread = std::thread(&ThreadObj::work, &obj);
                        	}
                        	void onMainThreadFinished() {
                        		bMainThreadRunning = true;
                        		m_thread.join();
                        	}
                        private:
                        	std::thread m_thread;
                        };
                        
                        int main(int argc, char *argv[])
                        {
                        	QApplication a(argc, argv);
                        	Obj o;
                        	o.start();
                        
                        	QWidget w;
                        	w.show();
                        
                        	auto ret = a.exec();
                        	o.onMainThreadFinished();
                        
                        	return 0;
                        }
                        
                        VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #15

                        @user4592357 said in main and background thread example:

                        ThreadObj obj;
                        m_thread = std::thread(&ThreadObj::work, &obj);

                        obj is allocated on the stack, it will go out of scope and delete itself

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        U 1 Reply Last reply
                        3
                        • VRoninV VRonin

                          @user4592357 said in main and background thread example:

                          ThreadObj obj;
                          m_thread = std::thread(&ThreadObj::work, &obj);

                          obj is allocated on the stack, it will go out of scope and delete itself

                          U Offline
                          U Offline
                          user4592357
                          wrote on last edited by
                          #16

                          @VRonin

                          hi, thanks for the reply.
                          the code has been modified since the first post (see my last code-post), so it's not the problem

                          1 Reply Last reply
                          0
                          • VRoninV Offline
                            VRoninV Offline
                            VRonin
                            wrote on last edited by
                            #17

                            https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            U 1 Reply Last reply
                            0
                            • VRoninV VRonin

                              https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

                              U Offline
                              U Offline
                              user4592357
                              wrote on last edited by
                              #18

                              @VRonin

                              i've read similar articles, saying "you shouldn't subclass QThread". in my case i need to do that.

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

                                Out of curiosity, what are you doing that requires to subclass QThread ?

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

                                U 1 Reply Last reply
                                0
                                • SGaistS SGaist

                                  Out of curiosity, what are you doing that requires to subclass QThread ?

                                  U Offline
                                  U Offline
                                  user4592357
                                  wrote on last edited by
                                  #20

                                  @SGaist

                                  nothing requires it. it's just that the whole implementation is done and i don't wanna change everything

                                  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