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. terminate While loop inside a QThread
Servers for Qt installer are currently down

terminate While loop inside a QThread

Scheduled Pinned Locked Moved Unsolved Qt for Python
7 Posts 3 Posters 627 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.
  • I Offline
    I Offline
    Igor86
    wrote on 9 Feb 2023, 16:18 last edited by Igor86 2 Sept 2023, 16:22
    #1

    Hi all!

    I have a situation that is beyond my knowledge and cant figure out how to solve this.

    I have a class, that runs on its own Thread. This class calls a method that has a while loop in it, that keeps checking a camera buffer to see if the image has been aquired.

    Problem is, i need in certain situations to be able to abort this while loop from the main thread (UI), but since it is in the same thread as my class I cannot figure out how to Stop it from outside, as teh whole worker is locked.

    Any help is appreciated...

    class UiMainWindow(QMainWindow):
        def __init__(self):
            self.thread = QThread()
            self.worker = Worker()       
            self.thread.started.connect(self.worker.load_camera)
            self.worker.finished.connect(self.thread.quit)
            self.thread.start()
    
    
    class Worker(QObject):
        def get_color(self, idin):
            try:
                color_img = crateColor.ColorImage(ia=self.ia, pool=self.pool, 
                machine_type=self.machine_type)
            except BaseException as be:
                print("Color recognition error:", be)
    

    cratecolor:

    class ColorImage:
        def __init__(self, ia=None, pool=str, machine_type=str):    
                self.abort = False
    
        def get_image(self):
            while not self.abort:
                buffer = self.ia.try_fetch(timeout=0)
                if buffer:
                     do stuff...
                     break
    
    

    is there a way to abort this while loop from the user Interface?
    Thanks to anybody willing to help me out..

    J 1 Reply Last reply 9 Feb 2023, 17:50
    0
    • I Igor86
      9 Feb 2023, 16:18

      Hi all!

      I have a situation that is beyond my knowledge and cant figure out how to solve this.

      I have a class, that runs on its own Thread. This class calls a method that has a while loop in it, that keeps checking a camera buffer to see if the image has been aquired.

      Problem is, i need in certain situations to be able to abort this while loop from the main thread (UI), but since it is in the same thread as my class I cannot figure out how to Stop it from outside, as teh whole worker is locked.

      Any help is appreciated...

      class UiMainWindow(QMainWindow):
          def __init__(self):
              self.thread = QThread()
              self.worker = Worker()       
              self.thread.started.connect(self.worker.load_camera)
              self.worker.finished.connect(self.thread.quit)
              self.thread.start()
      
      
      class Worker(QObject):
          def get_color(self, idin):
              try:
                  color_img = crateColor.ColorImage(ia=self.ia, pool=self.pool, 
                  machine_type=self.machine_type)
              except BaseException as be:
                  print("Color recognition error:", be)
      

      cratecolor:

      class ColorImage:
          def __init__(self, ia=None, pool=str, machine_type=str):    
                  self.abort = False
      
          def get_image(self):
              while not self.abort:
                  buffer = self.ia.try_fetch(timeout=0)
                  if buffer:
                       do stuff...
                       break
      
      

      is there a way to abort this while loop from the user Interface?
      Thanks to anybody willing to help me out..

      J Offline
      J Offline
      JonB
      wrote on 9 Feb 2023, 17:50 last edited by JonB 2 Sept 2023, 17:56
      #2

      @Igor86

      • I would use QThread::requestInterruption() from the UI and QThread::isInterruptionRequested() in the thread's while not ... test.

      • Or you could have your thread run() the Qt event loop and then send a signal from the UI where the worker has placed a slot.

      • Or I presume Python would allow you to go from the UI

      self.worker.color_img_member_variable.abort = True
      

      But I wouldn't recommend it :)

      As an aside, your

              while not self.abort:
                  buffer = self.ia.try_fetch(timeout=0)
      

      Depending on how that try_fetch(timeout=0) behaves, you may have a thread here which is very "busy" and uses up to 100% of its CPU time, you should check.

      I 1 Reply Last reply 10 Feb 2023, 06:59
      2
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 9 Feb 2023, 19:37 last edited by
        #3

        Hi,

        Beside the good point of @JonB and based on the code you show, your camera acquisition still happens in the main thread.

        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
        • J JonB
          9 Feb 2023, 17:50

          @Igor86

          • I would use QThread::requestInterruption() from the UI and QThread::isInterruptionRequested() in the thread's while not ... test.

          • Or you could have your thread run() the Qt event loop and then send a signal from the UI where the worker has placed a slot.

          • Or I presume Python would allow you to go from the UI

          self.worker.color_img_member_variable.abort = True
          

          But I wouldn't recommend it :)

          As an aside, your

                  while not self.abort:
                      buffer = self.ia.try_fetch(timeout=0)
          

          Depending on how that try_fetch(timeout=0) behaves, you may have a thread here which is very "busy" and uses up to 100% of its CPU time, you should check.

          I Offline
          I Offline
          Igor86
          wrote on 10 Feb 2023, 06:59 last edited by
          #4

          @JonB thank you very much! I't have some questions tough...

          for point (1) is there a way to revert the request once it has been set?
          for point (2), sorry, i didnt understand this point at all.. could you please elaborate a little bit?

          I set the timeout of the camera to 0.001 now and it is not locking up anymore. thanks for the tips!

          @SGaist , thank you for your answer. I noticed i removed the "move to thread" line while posting. I do have it in the code tough..

          Best regards

          J 1 Reply Last reply 10 Feb 2023, 07:52
          0
          • I Igor86
            10 Feb 2023, 06:59

            @JonB thank you very much! I't have some questions tough...

            for point (1) is there a way to revert the request once it has been set?
            for point (2), sorry, i didnt understand this point at all.. could you please elaborate a little bit?

            I set the timeout of the camera to 0.001 now and it is not locking up anymore. thanks for the tips!

            @SGaist , thank you for your answer. I noticed i removed the "move to thread" line while posting. I do have it in the code tough..

            Best regards

            J Offline
            J Offline
            JonB
            wrote on 10 Feb 2023, 07:52 last edited by JonB 2 Oct 2023, 07:55
            #5

            @Igor86 said in terminate While loop inside a QThread:

            for point (1) is there a way to revert the request once it has been set?

            There is no clearInterruption() method, so no. If you look at https://codebrowser.dev/qt5/qtbase/src/corelib/thread/qthread.cpp.html#_ZN7QThread19requestInterruptionEv you can see it's just a boolean flag wrapped in a QMutexLocker so you can do the same yourself on, say, your abort flag and allow clear if you wish. I have to say it's getting a bit weird that you want request an interruption and then change your mind.

            for point (2), sorry, i didnt understand this point at all.. could you please elaborate a little bit?

            See https://doc.qt.io/qt-6/qthread.html#details

            QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

            and read the run() and particularly the exec(). If you are running the Qt event loop you can communicate from the main thread to the worker thread via signals/slots. You would need to change while not self.abort: to something like a QTimer(1) so that the event loop is re-entered regularly, or maybe call QCoreApplication::processEvents() if you keep your while loop.

            As I wrote earlier, personally I would start by looking at whether your thread currently uses anywhere close to 100% CPU utilization. If it does then you need some kind of non-busy delay between every call to self.ia.try_fetch(timeout=0).

            I 2 Replies Last reply 10 Feb 2023, 09:16
            1
            • J JonB
              10 Feb 2023, 07:52

              @Igor86 said in terminate While loop inside a QThread:

              for point (1) is there a way to revert the request once it has been set?

              There is no clearInterruption() method, so no. If you look at https://codebrowser.dev/qt5/qtbase/src/corelib/thread/qthread.cpp.html#_ZN7QThread19requestInterruptionEv you can see it's just a boolean flag wrapped in a QMutexLocker so you can do the same yourself on, say, your abort flag and allow clear if you wish. I have to say it's getting a bit weird that you want request an interruption and then change your mind.

              for point (2), sorry, i didnt understand this point at all.. could you please elaborate a little bit?

              See https://doc.qt.io/qt-6/qthread.html#details

              QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

              and read the run() and particularly the exec(). If you are running the Qt event loop you can communicate from the main thread to the worker thread via signals/slots. You would need to change while not self.abort: to something like a QTimer(1) so that the event loop is re-entered regularly, or maybe call QCoreApplication::processEvents() if you keep your while loop.

              As I wrote earlier, personally I would start by looking at whether your thread currently uses anywhere close to 100% CPU utilization. If it does then you need some kind of non-busy delay between every call to self.ia.try_fetch(timeout=0).

              I Offline
              I Offline
              Igor86
              wrote on 10 Feb 2023, 09:16 last edited by
              #6

              @JonB Thank you very much!

              1 Reply Last reply
              0
              • J JonB
                10 Feb 2023, 07:52

                @Igor86 said in terminate While loop inside a QThread:

                for point (1) is there a way to revert the request once it has been set?

                There is no clearInterruption() method, so no. If you look at https://codebrowser.dev/qt5/qtbase/src/corelib/thread/qthread.cpp.html#_ZN7QThread19requestInterruptionEv you can see it's just a boolean flag wrapped in a QMutexLocker so you can do the same yourself on, say, your abort flag and allow clear if you wish. I have to say it's getting a bit weird that you want request an interruption and then change your mind.

                for point (2), sorry, i didnt understand this point at all.. could you please elaborate a little bit?

                See https://doc.qt.io/qt-6/qthread.html#details

                QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

                and read the run() and particularly the exec(). If you are running the Qt event loop you can communicate from the main thread to the worker thread via signals/slots. You would need to change while not self.abort: to something like a QTimer(1) so that the event loop is re-entered regularly, or maybe call QCoreApplication::processEvents() if you keep your while loop.

                As I wrote earlier, personally I would start by looking at whether your thread currently uses anywhere close to 100% CPU utilization. If it does then you need some kind of non-busy delay between every call to self.ia.try_fetch(timeout=0).

                I Offline
                I Offline
                Igor86
                wrote on 10 Feb 2023, 10:21 last edited by
                #7

                @JonB

                as per why I change my mind on the abort, I try to explain my situation:

                a external system sends a comand with a "job id" via TCP/IP to start the camera. at this point the software jumps into that loop and keeps checking the buffer waiting for the image. some time later, the external device triggers the camera with a digital contact and the image is in the buffer.
                What can happen tough, is that we get a new comand with a new job id, and have to abort the previous one and start the get_color again with the new id. (the worker is startet at startup and keeps running, its just the get_color that needs to be restarted).
                the idea was to request an abort on every new job id, so IF there is something running it will be aborted. But this means that the new get_color gets killed too. So I would need a way to reset that flag before I enter the loop, so i can be sure that on ENTERING the loop, its always false.

                But maybe there are better ways to do this. All I would need to do is to exit the get_color whenever the TCP gets a new jobId (tcp running on another Qtask) and start it over again with the new ID.

                hope the weird question makes a bit more sense now..

                1 Reply Last reply
                0

                1/7

                9 Feb 2023, 16:18

                • Login

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