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. Can't seem to start two QThreads one after the other from the same function.
Qt 6.11 is out! See what's new in the release blog

Can't seem to start two QThreads one after the other from the same function.

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 3 Posters 2.2k Views 1 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.
  • enjoysmathE Offline
    enjoysmathE Offline
    enjoysmath
    wrote on last edited by enjoysmath
    #1
        self._project.runner().eventOccurred.connect(self._sessionThread.stateMachineEventOccurs)
        self._sessionThread.setRunning(True)
        self._project.runStateMachine()
        self._sessionThread.start() 
        #self._project.runner().stateMachineStarted.connect(lambda: self._sessionThread.setRunning(True))
    

    If I comment out runStateMachine() which internally / directly / similarly starts another thread constructed as the same type of subclass of QThread; then self._sessionThread.start() will go through and work. But when they're both present, just the state machine starts, and I can't get the session thread to start ('run' I mean... nothing printed in run() method nor can I break there).

    JonBJ 1 Reply Last reply
    0
    • enjoysmathE Offline
      enjoysmathE Offline
      enjoysmath
      wrote on last edited by
      #2
      This post is deleted!
      1 Reply Last reply
      0
      • enjoysmathE enjoysmath
            self._project.runner().eventOccurred.connect(self._sessionThread.stateMachineEventOccurs)
            self._sessionThread.setRunning(True)
            self._project.runStateMachine()
            self._sessionThread.start() 
            #self._project.runner().stateMachineStarted.connect(lambda: self._sessionThread.setRunning(True))
        

        If I comment out runStateMachine() which internally / directly / similarly starts another thread constructed as the same type of subclass of QThread; then self._sessionThread.start() will go through and work. But when they're both present, just the state machine starts, and I can't get the session thread to start ('run' I mean... nothing printed in run() method nor can I break there).

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #3

        @enjoysmath
        QThread::start() does nothing if the thread is already running.

        If I comment out runStateMachine() which internally / directly / similarly starts another thread constructed as the same type of subclass of QThread;

        You sure they're not running on the same thread? Just a thought.

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

          Hi,

          @enjoysmath said in Can't seem to start two QThreads one after the other from the same function.:

          self._sessionThread.setRunning(True)
          self._project.runStateMachine()
          self._sessionThread.start()

          Something strange here, why both setRunning and start ?

          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
          • enjoysmathE Offline
            enjoysmathE Offline
            enjoysmath
            wrote on last edited by
            #5

            @SGaist the reason I do that is because I can't seem to override start() in my QThread subclasses, which would normally do the job of setRunning(True).

            Essentially I want two independent threads

            1 Reply Last reply
            0
            • JonBJ JonB

              @enjoysmath
              QThread::start() does nothing if the thread is already running.

              If I comment out runStateMachine() which internally / directly / similarly starts another thread constructed as the same type of subclass of QThread;

              You sure they're not running on the same thread? Just a thought.

              enjoysmathE Offline
              enjoysmathE Offline
              enjoysmath
              wrote on last edited by
              #6

              @JonB , @SGaist

              0_1556137519633_880c3468-a992-40f5-be58-6fcbecf48e4e-image.png

              Here's what I'm working on. Of course I'd need a separate thread to run the state machine and a thread to run the recorder. I don't want to mix the two, and they cannot block the GUI!

              Thanks for any links / guidance.

              What's that article about how to choose the right Qt Threading solution?

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

                Because start is not a virtual function.

                @enjoysmath said in Can't seem to start two QThreads one after the other from the same function.:

                _project.runStateMachine

                How is that method implemented ?

                And why a thread for your state machine ? QStateMachine already spins it's own event loop so you don't really need a separate thread for it.

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

                enjoysmathE 1 Reply Last reply
                2
                • SGaistS SGaist

                  Because start is not a virtual function.

                  @enjoysmath said in Can't seem to start two QThreads one after the other from the same function.:

                  _project.runStateMachine

                  How is that method implemented ?

                  And why a thread for your state machine ? QStateMachine already spins it's own event loop so you don't really need a separate thread for it.

                  enjoysmathE Offline
                  enjoysmathE Offline
                  enjoysmath
                  wrote on last edited by enjoysmath
                  #8

                  @SGaist

                  I'm not using QStateMachine - because it had no particular features I was going to use. This is a DSL for leds (the text), so no keyboard events.

                  My state machine runner works, though is kind of iffy, but definitely depends on being run on a QRunnable or QThread.

                  @SGaist thanks for your quick response!

                  😁
                  🌵

                  1 Reply Last reply
                  0
                  • enjoysmathE Offline
                    enjoysmathE Offline
                    enjoysmath
                    wrote on last edited by enjoysmath
                    #9

                    I've changed it to QThreadPool with two QRunnables started() on it. But I think it's still doing the same thing - only one thread at a time.

                    ```
                    

                    def killStateMachine(self):
                    self._window.scene.setInSimulation(False)
                    self._runner.abort()

                    def runStateMachine(self):
                        thread = self.createRunnerThread()
                        thread.setRunning(True)
                        thread.start()
                    
                    def createRunnerThread(self):
                        start_state = self.getStartState()
                        if start_state:
                            self._window.scene.setInSimulation(True)
                            self._runner.setStartState(start_state)
                            return self._runner.createThread()
                        else:
                            self._window.showStatusMessage( 
                                "No start state found.  Make sure there's a state with no arrows going into it.",
                                7000, 'color:maroon;')
                        return None
                    
                    
                    My impls kindof confusing.  Should I work on a minimal example?
                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      That would be nice yes.

                      It seems to be really convoluted. Rather than having a thread handling your object (like the worker object concept) you seem to create the thread from the object itself and then ??

                      Also, you seem to want to modify your GUI from these threads which is wrong.

                      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
                      2
                      • enjoysmathE Offline
                        enjoysmathE Offline
                        enjoysmath
                        wrote on last edited by enjoysmath
                        #11

                        Here's what I think is going on now. I saw that the internals of my RunnerThread class have been replaced with a QTimer. Probably from when I was having some unrelated problems with QThreads.

                        So my first thought was to convert both thread classes to QTimers internally (effectively not using the thread). But as I was coding this idea, I thought wait, maybe the threads aren't working because:

                        ```
                        
                        def start(self):
                            self._loopTimer = QTimer()
                            sleep = self._runner.tickSleep()
                            self._loopTimer.setInterval(sleep)
                            self._loopTimer.timeout.connect(self.run)
                            self._loopTimer.setSingleShot(False)        
                            self._loopTimer.start()
                            self._state = self._runner.startState()
                            self.setRunning(True)
                            self.exec()         # Start Qt event loop
                        
                        def terminate(self):
                            self.setRunning(False)
                            self._loopTimer.stop()
                            self._loopTimer = None
                        

                        I think maybe that self.exec() call is not returning or if it is you can't do what I've done with a QTimer and another QThread implemented the appropriate way.

                        I'll put them both back as real QThreads, and see if that solves this.

                        1 Reply Last reply
                        0
                        • enjoysmathE Offline
                          enjoysmathE Offline
                          enjoysmath
                          wrote on last edited by
                          #12

                          Okay, here's my findings.

                          First read the article by Qt about the different threading options. If yours is QThread, then implement them as usual, but create a startRunning / stopRunning methods (in your subclass) which call start / terminate since these methods are not overridable.

                          Any time I switch on an LED or make a change graphically from the state machine runner thread, I need to implement that as a signal / slot and do the actual LED brightness change in say my MainWindow class, but in the main gui thread is what's important. If you just try to change an LED's brightness you'll notice nothing changes on screen. It's because your graphics scene is running on the main gui thread I think. With QThreads (unlike QRunnable) you can add your pyqtSignals's directly to your QThread subclass.

                          You can also make a QThread pauseable. Message me if you need to know how.

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

                            The exec call indeed doesn't return until the loop it started ends.

                            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