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. QRunnable and QThreadPool: how to interrupt the task?
QtWS25 Last Chance

QRunnable and QThreadPool: how to interrupt the task?

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 19.8k Views
  • 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.
  • V Offline
    V Offline
    voltron
    wrote on last edited by
    #1

    I trying to identify the best approach to use for my PyQt application. The program has multiple independent data-processing tools which I want to run in separate threads to keep GUI responsive and allow user to process several datasets at once.

    As I understand, I can use QThreads + worker objects + my own thread queue implementation or alternatively use QThreadPool and QRunnables. I already found how I can emit signals from QRunnable (e.g. to report progress or show messages), but I can not find is it possible to interrupt QRunnable?

    Ability to interrupt is really necessary as some processes may be very long-running and users should have ability to stop them. So my question is: can I interrupt QRunnable and if yes, how to do it?

    Thanks for your replies.

    1 Reply Last reply
    0
    • T Offline
      T Offline
      ttuna
      wrote on last edited by
      #2

      Multithreading Technologies in Qt
      At the bottom you can find a table 'Choosing an Appropriate Approach'. Hope this will help you.

      V 1 Reply Last reply
      0
      • T Offline
        T Offline
        ttuna
        wrote on last edited by
        #3

        #yolo - have some time to spare so here is the longer answer :-)

        If your QRunnable derived object lives (- is created) in a thread with event loop, you can implement a slot to access a flag (-lets call it bool m_running).

        In your run() method you can check on this flag and leave if .e.g. m_running == false.
        I don't know if you have a loop in your run() implementation. If not maybe you can use some timers to repeatedly check the m_running flag (- i have to mention that a QTimer needs a event loop!!!)

        Maybe you will have to implement some QMutex for your flag, because you are accessing it from two (-or more) threads.

        BR

        1 Reply Last reply
        0
        • T ttuna

          Multithreading Technologies in Qt
          At the bottom you can find a table 'Choosing an Appropriate Approach'. Hope this will help you.

          V Offline
          V Offline
          voltron
          wrote on last edited by
          #4

          @ttuna thanks for your reply.
          I already read documentation mentioned by you. My use case is similar to "One call" so both approaches: QThread or QRunnable should be fine.
          Also I need to need to update progress/cancel operation and again both approaches can do this. QThread can emit and accept signals, QRunnable — can not. But with QRunnable I can have dummy QObject for emmiting signals. The only thing I miss with QRunnable is the ability to stop it.

          Thanks for the hint with bool flag, I will look if it is possible to implement it.

          kshegunovK 1 Reply Last reply
          0
          • V voltron

            @ttuna thanks for your reply.
            I already read documentation mentioned by you. My use case is similar to "One call" so both approaches: QThread or QRunnable should be fine.
            Also I need to need to update progress/cancel operation and again both approaches can do this. QThread can emit and accept signals, QRunnable — can not. But with QRunnable I can have dummy QObject for emmiting signals. The only thing I miss with QRunnable is the ability to stop it.

            Thanks for the hint with bool flag, I will look if it is possible to implement it.

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by
            #5

            @voltron
            Hello,

            The only thing I miss with QRunnable is the ability to stop it.

            Right, so how do you stop QThread? Think about it, QRunnable is an atomic task that should be executed on a free thread from the pool. Then if you're using a worker QObject your atomic tasks are the slots that are executing. For the worker object you also have no way of stopping the thread mid-processing, aside from manually synchronizing a flag that tells you you have to stop doing what you're doing and setting it through a direct call from the outside. But in the end this should be possible with QRunnable, no?

            Kind regards.

            Read and abide by the Qt Code of Conduct

            V 1 Reply Last reply
            0
            • kshegunovK kshegunov

              @voltron
              Hello,

              The only thing I miss with QRunnable is the ability to stop it.

              Right, so how do you stop QThread? Think about it, QRunnable is an atomic task that should be executed on a free thread from the pool. Then if you're using a worker QObject your atomic tasks are the slots that are executing. For the worker object you also have no way of stopping the thread mid-processing, aside from manually synchronizing a flag that tells you you have to stop doing what you're doing and setting it through a direct call from the outside. But in the end this should be possible with QRunnable, no?

              Kind regards.

              V Offline
              V Offline
              voltron
              wrote on last edited by
              #6

              @kshegunov thanks a lot for your reply.

              Usually, when I use QThread for long running task I have a loop inside thread or worker object where all data-processing happens. And before each iteration I just check bool flag "interrupt" and break loop if this flag is set.

              I never used QRunnable before so I don't know if it is possible to change flag from outside, e.g. by emitting a signal in the GUI thread and handling it in the QRunnable. As i said in my previous post I will try to create small test app for this case.

              kshegunovK 1 Reply Last reply
              0
              • V voltron

                @kshegunov thanks a lot for your reply.

                Usually, when I use QThread for long running task I have a loop inside thread or worker object where all data-processing happens. And before each iteration I just check bool flag "interrupt" and break loop if this flag is set.

                I never used QRunnable before so I don't know if it is possible to change flag from outside, e.g. by emitting a signal in the GUI thread and handling it in the QRunnable. As i said in my previous post I will try to create small test app for this case.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #7

                @voltron
                Right, only you wouldn't handle the signal as Qt::QueuedConnection as it's usually done. Consider this very simple example:

                class MyRunnable : public QRunnable
                {
                public:
                    void requestInterruption()
                    {
                        interrupt.testAndSetOrdered(0, 1);
                    }
                
                    bool isInterruptionRequested() const
                    {
                        return static_cast<int>(interrupt);
                    }
                
                private:
                    QAtomicInt interrupt;
                };
                

                Then call the functions how you'd usually do with QThread.

                Kind regards.

                Read and abide by the Qt Code of Conduct

                T V 2 Replies Last reply
                3
                • kshegunovK kshegunov

                  @voltron
                  Right, only you wouldn't handle the signal as Qt::QueuedConnection as it's usually done. Consider this very simple example:

                  class MyRunnable : public QRunnable
                  {
                  public:
                      void requestInterruption()
                      {
                          interrupt.testAndSetOrdered(0, 1);
                      }
                  
                      bool isInterruptionRequested() const
                      {
                          return static_cast<int>(interrupt);
                      }
                  
                  private:
                      QAtomicInt interrupt;
                  };
                  

                  Then call the functions how you'd usually do with QThread.

                  Kind regards.

                  T Offline
                  T Offline
                  ttuna
                  wrote on last edited by
                  #8

                  @kshegunov
                  Atomic flag ... nice idea :-)

                  kshegunovK 1 Reply Last reply
                  0
                  • T ttuna

                    @kshegunov
                    Atomic flag ... nice idea :-)

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

                    @ttuna
                    Thanks, I couldn't claim credit though. It's used extensively in the reference counting mechanism in Qt (i.e. for implicit sharing, smart pointers and so on). :)

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0
                    • kshegunovK kshegunov

                      @voltron
                      Right, only you wouldn't handle the signal as Qt::QueuedConnection as it's usually done. Consider this very simple example:

                      class MyRunnable : public QRunnable
                      {
                      public:
                          void requestInterruption()
                          {
                              interrupt.testAndSetOrdered(0, 1);
                          }
                      
                          bool isInterruptionRequested() const
                          {
                              return static_cast<int>(interrupt);
                          }
                      
                      private:
                          QAtomicInt interrupt;
                      };
                      

                      Then call the functions how you'd usually do with QThread.

                      Kind regards.

                      V Offline
                      V Offline
                      voltron
                      wrote on last edited by voltron
                      #10

                      @kshegunov
                      Thanks a lot! I modified your example a bit to use QMutex to protect flag when changing it. Need to use QMutex because in PyQt4 there is no QAtomicInt.
                      Thanks again for your help.

                      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