Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved QRunnable and QThreadPool: how to interrupt the task?

    General and Desktop
    3
    10
    16670
    Loading More Posts
    • 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
      voltron last edited by

      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 Reply Quote 0
      • T
        ttuna last edited by

        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 Reply Quote 0
        • T
          ttuna last edited by

          #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 Reply Quote 0
          • V
            voltron @ttuna last edited by

            @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.

            kshegunov 1 Reply Last reply Reply Quote 0
            • kshegunov
              kshegunov Moderators @voltron last edited by

              @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 Reply Quote 0
              • V
                voltron @kshegunov last edited by

                @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.

                kshegunov 1 Reply Last reply Reply Quote 0
                • kshegunov
                  kshegunov Moderators @voltron last edited by 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.

                  Read and abide by the Qt Code of Conduct

                  T V 2 Replies Last reply Reply Quote 3
                  • T
                    ttuna @kshegunov last edited by

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

                    kshegunov 1 Reply Last reply Reply Quote 0
                    • kshegunov
                      kshegunov Moderators @ttuna last edited by

                      @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 Reply Quote 0
                      • V
                        voltron @kshegunov last edited by voltron

                        @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 Reply Quote 0
                        • First post
                          Last post