Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Threads not working simultaneously
Forum Updated to NodeBB v4.3 + New Features

Threads not working simultaneously

Scheduled Pinned Locked Moved Unsolved Qt for Python
11 Posts 4 Posters 1.7k 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.
  • F Offline
    F Offline
    fizdiz
    wrote on 13 Jul 2021, 23:25 last edited by fizdiz
    #1

    I am trying to get 2 threads to work simultaneously.

    import sys
    
    from PyQt5 import QtWidgets
    from PyQt5.QtCore import QObject, QThread
    
    
    class Worker(QObject):
        def run(self, str):
            while True:
                print(str)
    
    
    class ThreadController():
        def __init__(self):
            # Thread 1
            self.thread = QThread()
            self.worker = Worker()
            self.worker.moveToThread(self.thread)
            self.thread.started.connect(lambda:self.worker.run('worker1'))
            self.thread.start()
    
            # Thread 2
            self.thread2 = QThread()
            self.worker2 = Worker()
            self.worker2.moveToThread(self.thread2)
            self.thread2.started.connect(lambda:self.worker2.run('worker2'))
            self.thread2.start()
    
    
    if __name__=='__main__':
        app = QtWidgets.QApplication(sys.argv)
        thread = ThreadController()
        sys.exit(app.exec_())
    

    This should print "worker1" and "worker2". However I'm only seeing the output "worker1".
    How can I fix this?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      sierdzio
      Moderators
      wrote on 14 Jul 2021, 05:35 last edited by
      #2

      It could be that threads run OK but the print() is so much flooded with messages from the first thread that it can't display any of thread2 messages.

      Try introducing some small sleep to your thread loop, to give print some space to breathe.

      (Z(:^

      1 Reply Last reply
      1
      • F Offline
        F Offline
        fizdiz
        wrote on 14 Jul 2021, 08:27 last edited by
        #3

        I've tried that, but worker2 still doesn't print anything.

        class Worker(QObject):
            def run(self, str):
                while True:
                    print(str)
                    time.sleep(1)
        
        J 1 Reply Last reply 14 Jul 2021, 08:37
        0
        • F fizdiz
          14 Jul 2021, 08:27

          I've tried that, but worker2 still doesn't print anything.

          class Worker(QObject):
              def run(self, str):
                  while True:
                      print(str)
                      time.sleep(1)
          
          J Offline
          J Offline
          JonB
          wrote on 14 Jul 2021, 08:37 last edited by
          #4

          @fizdiz
          I don't know, but start out with a bit more debugging:

          • Put in print() statement immediately above self.thread2.start(). Does it get hit?
          • Remove while True in Worker so it just print(str) once. Do you see both threads run?
          • Replace while True with for i in range(100). Do you see thread2 messages as well as thread1 ones now?
          F 1 Reply Last reply 14 Jul 2021, 09:09
          1
          • J JonB
            14 Jul 2021, 08:37

            @fizdiz
            I don't know, but start out with a bit more debugging:

            • Put in print() statement immediately above self.thread2.start(). Does it get hit?
            • Remove while True in Worker so it just print(str) once. Do you see both threads run?
            • Replace while True with for i in range(100). Do you see thread2 messages as well as thread1 ones now?
            F Offline
            F Offline
            fizdiz
            wrote on 14 Jul 2021, 09:09 last edited by
            #5

            @JonB
            I've done the things you suggested and it seems that thread2 is actually executed, but the print statements of worker2 are printed only after worker1 stops printing.

            However, this solves my problem as it has been shown that it's not a problem with the threads but with my code which is running in the threads.

            Thanks!

            J 1 Reply Last reply 14 Jul 2021, 09:47
            1
            • F fizdiz
              14 Jul 2021, 09:09

              @JonB
              I've done the things you suggested and it seems that thread2 is actually executed, but the print statements of worker2 are printed only after worker1 stops printing.

              However, this solves my problem as it has been shown that it's not a problem with the threads but with my code which is running in the threads.

              Thanks!

              J Offline
              J Offline
              JonB
              wrote on 14 Jul 2021, 09:47 last edited by JonB
              #6

              @fizdiz
              This implies that Python's time.sleep(1) in a thread does not "relinquish control", such that another thread can run. Which I find surprising as I have seen other people use that from Python threads.

              I am not a Python super-expert, but I know there is a "wrinkle" with multiple threads in Python (which does not arise in C++). Python's interpreter, named "GIL", is required to execute all Python code. When multi-threading, only one instance of the GIL can run at any one time, i.e. the Python interpreter is not multi-thread-re-entrant. It looks like time.sleep() is still executed by the GIL such that it does not allow another thread to get the GIL. You may have to investigate further.....

              J 1 Reply Last reply 14 Jul 2021, 11:15
              1
              • J JonB
                14 Jul 2021, 09:47

                @fizdiz
                This implies that Python's time.sleep(1) in a thread does not "relinquish control", such that another thread can run. Which I find surprising as I have seen other people use that from Python threads.

                I am not a Python super-expert, but I know there is a "wrinkle" with multiple threads in Python (which does not arise in C++). Python's interpreter, named "GIL", is required to execute all Python code. When multi-threading, only one instance of the GIL can run at any one time, i.e. the Python interpreter is not multi-thread-re-entrant. It looks like time.sleep() is still executed by the GIL such that it does not allow another thread to get the GIL. You may have to investigate further.....

                J Offline
                J Offline
                jeremy_k
                wrote on 14 Jul 2021, 11:15 last edited by
                #7

                @JonB said in Threads not working simulataneously:

                @fizdiz
                This implies that Python's time.sleep(1) in a thread does not "relinquish control", such that another thread can run. Which I find surprising as I have seen other people use that from Python threads.

                I am not a Python super-expert, but I know there is a "wrinkle" with multiple threads in Python (which does not arise in C++). Python's interpreter, named "GIL",

                GIL is an acronym of Global Interpreter Lock. A python statement can change global state, including redefining functions. The widely used CPython (aka $PATH/python most of the time) implementation simplifies the the situation by only allowing one thread to run at a time. A thread may yield between statements (or maybe it's a sequence point), but nothing interpreted runs simultaneously.

                PyQt, and probably PySide release the lock when calling native/C++ code. I think the lesson is clear. Prefer C++ =-)

                Asking a question about code? http://eel.is/iso-c++/testcase/

                J 1 Reply Last reply 14 Jul 2021, 11:29
                0
                • J jeremy_k
                  14 Jul 2021, 11:15

                  @JonB said in Threads not working simulataneously:

                  @fizdiz
                  This implies that Python's time.sleep(1) in a thread does not "relinquish control", such that another thread can run. Which I find surprising as I have seen other people use that from Python threads.

                  I am not a Python super-expert, but I know there is a "wrinkle" with multiple threads in Python (which does not arise in C++). Python's interpreter, named "GIL",

                  GIL is an acronym of Global Interpreter Lock. A python statement can change global state, including redefining functions. The widely used CPython (aka $PATH/python most of the time) implementation simplifies the the situation by only allowing one thread to run at a time. A thread may yield between statements (or maybe it's a sequence point), but nothing interpreted runs simultaneously.

                  PyQt, and probably PySide release the lock when calling native/C++ code. I think the lesson is clear. Prefer C++ =-)

                  J Offline
                  J Offline
                  JonB
                  wrote on 14 Jul 2021, 11:29 last edited by
                  #8

                  @jeremy_k
                  Yes, but unfortunately I don't see how this tells us why OP says second thread does not run/print while first thread calls time.sleep(), which I have seen others use in Python threads so one would have thought would yield and work.....

                  S J F 3 Replies Last reply 14 Jul 2021, 11:32
                  0
                  • J JonB
                    14 Jul 2021, 11:29

                    @jeremy_k
                    Yes, but unfortunately I don't see how this tells us why OP says second thread does not run/print while first thread calls time.sleep(), which I have seen others use in Python threads so one would have thought would yield and work.....

                    S Offline
                    S Offline
                    sierdzio
                    Moderators
                    wrote on 14 Jul 2021, 11:32 last edited by
                    #9

                    @JonB said in Threads not working simulataneously:

                    @jeremy_k
                    Yes, but unfortunately I don't see how this tells us why OP says second thread does not run/print while first thread calls time.sleep(), which I have seen others use in Python threads so one would have thought would yield and work.....

                    This might be actually unrelated to Python. Remember that print is a system call and OS has to synchronize it between many threads and many processes. I've seen many situations where even C++ & Qt would also only print from one thread and only display the remaining messages after you close the app.

                    (Z(:^

                    1 Reply Last reply
                    1
                    • J JonB
                      14 Jul 2021, 11:29

                      @jeremy_k
                      Yes, but unfortunately I don't see how this tells us why OP says second thread does not run/print while first thread calls time.sleep(), which I have seen others use in Python threads so one would have thought would yield and work.....

                      J Offline
                      J Offline
                      jeremy_k
                      wrote on 14 Jul 2021, 11:34 last edited by jeremy_k
                      #10

                      @JonB I wasn't addressing OP's issue, but rather the python interpreter is called "GIL" comment, and implications the global lock has on parallelism.

                      To the best of my knowledge, python makes no promises about fairness of thread scheduling. I try to code my routines to finish their computation and get out of the way rather than busy wait.

                      Edit: The same goes for C++.

                      Asking a question about code? http://eel.is/iso-c++/testcase/

                      1 Reply Last reply
                      0
                      • J JonB
                        14 Jul 2021, 11:29

                        @jeremy_k
                        Yes, but unfortunately I don't see how this tells us why OP says second thread does not run/print while first thread calls time.sleep(), which I have seen others use in Python threads so one would have thought would yield and work.....

                        F Offline
                        F Offline
                        fizdiz
                        wrote on 16 Jul 2021, 11:37 last edited by
                        #11

                        @JonB I still don't know why the print messages are not printed simultaneously. It seems like the program waits for the loop in one thread to finish, before starting the loop in the next thread.

                        I don't think that it has to do with the fact that print is a system call. I have written similar code which starts a loop in a thread to update a button in a GUI, but the GUI doesn't show until the thread is finished.

                        It also doesn't seem to be an issue with Python's built-in time.sleep() , as I get the same issue with Qt's QThread.sleep()

                        So I still don't know how to fix the above issue.

                        1 Reply Last reply
                        0

                        1/11

                        13 Jul 2021, 23:25

                        • Login

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