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.2k 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
    #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