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 user4592357
    #1

    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 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      @user4592357 said in main and background thread example:

      void onMainThreadFinished() {
      bMainThreadRunning = true;
      m_thread.join();
      }

      Shouldn't that be bMainThreadRunning = false; ?

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

        my bad, that's right, i tried to implement what's in my actual project in a snippet and that's what i got automatically.
        but anyways that's not the result i expect. what i expect is, when the main thread finishes i need the background thread to be notified and finish immediately, but with this code it was for the interval to exit.
        actually in my actual project i implemented that scenario, it's basically the same code but then i had to change the places where all of these objects are created and this is the result i get.

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

          Well, if you thread just started to sleep, you'll have to wait for your 5 seconds before it ends properly.

          Do you really have that kind of loop in your application ? It could be reworked to use e.g. a QTimer in 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
          0
          • 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