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. Best practices with QRunnable
Forum Updated to NodeBB v4.3 + New Features

Best practices with QRunnable

Scheduled Pinned Locked Moved General and Desktop
10 Posts 5 Posters 27.9k 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.
  • JKSHJ Offline
    JKSHJ Offline
    JKSH
    Moderators
    wrote on last edited by
    #1

    We've heard many times why we shouldn't subclass QThread (http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong )

    What about QRunnable? It's designed to be subclassed like how QThread used to be. It's somewhat safer since people can't add slots to it, but the flipside is that it can't emit signals to notify the world that it has finished.

    The only example I could find that shows QRunnable in action is http://doc-snapshot.qt-project.org/5.0/thread-basics.html#example-1-using-the-thread-pool , but it's a trivial example. Does anyone know of any useful examples?

    What are some recommended ways to return a result from QRunnable?

    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

    1 Reply Last reply
    0
    • R Offline
      R Offline
      rcari
      wrote on last edited by
      #2

      Well I would not use QRunnable. Maybe you should take a look at "QtConcurrent":http://qt-project.org/doc/qt-4.8/qtconcurrent.html which provide a future API that allows you to retrieve a result from an asynchronous computation. You can also watch the future with a QFutureWatcher which emits a signal when the computation is done.

      1 Reply Last reply
      0
      • K Offline
        K Offline
        KeithS
        wrote on last edited by kshegunov
        #3

        Where do you get the idea that "the flipside is that it can’t emit signals to notify the world that it has finished"?

        Here's an example I've used that features a subclass of QRunnable and QObject to create some user task that should be run threaded:

        class tileTask : public QObject, public QRunnable
        {
          Q_OBJECT
        
        public:
        ...
        
          void run() {
            // do the task work here
            ...
            // say we're done
            emit finished();
          }
        
        signals:
          void finished();
        ...
        };
        
        Then to thread the operations, use QThreadPool:
        
        void
        myThreadingExample()
        {
          QQueue<tileTask *> jobs;
          // Here we take some data e.g. an image that has been tiled
          // and stuff the tiles into a queue.
          int numTasks = maxx * maxy;
          for (int x=0; x < maxx; ++x) {
            for (int y=0; y < maxy; ++y) {
              tileTask *task = new tileTask(imageData(x, y));
              jobs.enqueue(task);
              task->setAutoDeletet(true);
            }
          }
        
          QThreadPool *threadPool = QThreadPool::globalInstance();
          for (int i=0; i < numTasks; ++i) {
            tileTask *newTask = jobs.dequeue()
            threadPool->start(newTask)
            QObject::connect(newTask, SIGNAL(finished()), this, SLOT(threadFinished()), Qt::QueuedConnection);
          }
        
          // Wait for all threads to finish
          threadpool->waitForDone();
        }
        

        The threadFinished() slot called by the task on completion just updated a progress bar and called qApp->processEvents() just to keep the gui updated.

        QtConcurrent() may well be a neater method of achieving this, but I've not looked at it closely yet.

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          Thanks for your replies, rcari and KeithS.

          I asked because I'm updating Qt's multithreading documentation, and would like to find out how people use the different thread-related technologies (QThread, QRunnable and QtConcurrent). I'm also interested in learning about the strengths+weaknesses of each. There's currently a little debate over whether QtConcurrent should be re-written.

          [quote author="rcari" date="1353260562"]Well I would not use QRunnable[/quote]Would you mind sharing why you'd avoid QRunnable? Did you encounter problems with it, or is it just that QtConcurrent serves your purposes already?

          [quote author="KeithS" date="1353321819"]Where do you get the idea that "the flipside is that it can’t emit signals to notify the world that it has finished"?

          Here's an example I've used that features a subclass of QRunnable and QObject to create some user task that should be run threaded[/quote]Ah, of course; I forgot about multiple inheritance. Thank you for your insightful example.

          This approach makes QRunnable more flexible -- like QThread, but with the added benefit of auto-cleanup and management by QThreadPool. I wonder if popularizing this approach will lead to the same issues that plagued QThread before, though.

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          0
          • R Offline
            R Offline
            rcari
            wrote on last edited by
            #5

            Well, QRunnable is fine, but it does not take away the burden of actually running that thing. With QtConcurrent, you call a method, asynchronously. It's just a function call in a pretty wrapper. I don't have to care about thread creation, termination or pools... Everything is managed for me. Plus, since it is a simple function call, it usually avoids some of the pitfalls of concurrency when used in a pure functional way. I give it const input data and I get the result asynchronously: perfect.
            However, I think QtConcurrent lacks the ability to customize the QFuture. For example, there is no way to deliver progress information from the @QtConcurrent::run@ as this is only reserved to the higher level filter/map/reduce APIs provided by Qt. In a similar fashion, many custom computations could benefit from the @QFuture::cancel()@ call. This would make it the perfect solution for doing asynchronous work.

            1 Reply Last reply
            0
            • K Offline
              K Offline
              KeithS
              wrote on last edited by
              #6

              I see nothing wrong with QRunnable. That's not to say I see no value on QtConcurrent - far from it, the more the complexities of thread programming can be managed at a higher level the better, as we are all going to be embracing multithreading more and more in the future. However, as rcari points out, QtConcurrent isn't all there yet. It's nice it works on QList, QLinkedList, QVector, but in practise I might just want to run on some specific data structure which is doesn't support.

              1 Reply Last reply
              0
              • R Offline
                R Offline
                rcari
                wrote on last edited by
                #7

                Well perhaps the best of both worlds would be to have the ability to push a QRunnable to QtConcurrent and to have additional methods on that QRunnable to provide progress information and cancellation control eg:
                @
                void setProgress( qint64 progress, qint64 maxProgress );
                bool isCanceled() const;
                @
                This is kind of what I did on a personal projet with what I called a "Tasklet":https://github.com/rcari/libKore/blob/master/source/src/parallel/Tasklet.cpp.

                1 Reply Last reply
                0
                • JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by
                  #8

                  I think there is value in having both low-level (QRunnable) and high-level (QtConcurrent) APIs, and letting them communicate with each other. That would cover the need for easy-to-use and robust concurrency, as well as the ability to fine-tune performance, as well as everything in between.

                  I've mainly used worker objects with QThread, as I find that it fits well with Qt's signal-slot mechanism. I've recently learnt that it's not as scalable as using a thread pool though. Have either of you used QThread much in your work? (rcari, I notice that you use QThread to determine the active thread; do you also use it to manage your tasks?)

                  By the way, I forgot to provide links in my last post. If you're interested in weighing in on the discussion on QtConcurrent's future, have a look at the Development mailing list (they're currently thinking of introducing KDE's ThreadWeaver or Intel's Thread Building Blocks into Qt):

                  http://lists.qt-project.org/pipermail/development/2012-November/007921.html
                  http://lists.qt-project.org/pipermail/development/2012-November/007952.html
                  http://lists.qt-project.org/pipermail/development/2012-November/007901.html

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    INeedMySpace
                    wrote on last edited by
                    #9

                    As for my experience subclassing QThread works well while we start event loop with exec in run and triggering signals/slots outside. I haven't tested yet new approach with QThread as manager for other class based on QObject.

                    You have been involved in illegal use of magic.

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      mlong
                      wrote on last edited by
                      #10

                      @INeedMySpace

                      There's no argument that subclassing QThread can work -- and indeed it was the only way to use QThread in earlier versions of Qt -- but since that method is rife with potential problems, that particular methodology is deprecated for most common applications and should be avoided if possible.

                      Software Engineer
                      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                      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