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. What's the correct way of using QThread?
Forum Updated to NodeBB v4.3 + New Features

What's the correct way of using QThread?

Scheduled Pinned Locked Moved General and Desktop
9 Posts 6 Posters 9.0k 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
    ivan.todorovich
    wrote on last edited by
    #1

    Hi,

    I'm starting a new project that basically consists of a set of worker classes (a parser, a socket manager, etc) and a GUI.

    The GUI has to be fluid. I want the main thread to contain only the GUI. And a separate thread that holds the worker classes.

    I wonder what's the correct way of doing this, since Qt Docs are a little fuzzy regarding QThreads. QtDocs suggest subclassing QThread and reimplementing run(). But on the other hand, a while ago I've read a blog post saying that the correct way of using QThreads is calling the moveToThread method. Unfortunately I can't seem to find that blog post again :(

    Currently I have this:

    @
    #include <QtGui/QApplication>
    #include "MainWindow.h"
    #include <QtDebug>

    #include <QThread>

    #include "CAbstractParser.h"

    int main(int argc, char *argv[])
    {

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    
    cLog->notice("==========================================");
    cLog->notice("STARTING UP...");
    cLog->notice("==========================================");
    
    QThread workThread(qApp);
    
    CAbstractParser parser("C:/Users/User/Desktop/test.log");
    parser.moveToThread(&workThread);
    parser.connect(&workThread, SIGNAL(started()), SLOT(start()));
    parser.connect(&workThread, SIGNAL(finished()), SLOT(stop()));
    
    workThread.connect(qApp, SIGNAL(aboutToQuit()), SLOT(quit()));
    workThread.start();
    
    return a.exec&#40;&#41;;
    

    }
    @

    CLogger is a Singleton. It has a CLogger::instance() method to retreive the singleton class. cLog is a macro meaning CLogger::instance(). ( Just like qApp and QApplication::instance() )

    MainWindow will connect to a SIGNAL of cLog on constructor, so this is where CLogger's instance is created.

    CAbstractParser starts a timer with start(), and kills it with stop(). Every 1000ms, parser will 'parse' new lines of a specified log file.
    Sometimes CAbstractParser will log something with cLog->notice("Something")

    I'm getting a warning when closing the program and I don't know why or how to remove it:
    @QObject::killTimers: timers cannot be stopped from another thread@

    o_o Sorry for my rusted english.

    1 Reply Last reply
    0
    • I Offline
      I Offline
      ivan.todorovich
      wrote on last edited by
      #2

      [quote author="ivan.todorovich" date="1298994374"]

      I'm getting a warning when closing the program and I don't know why or how to remove it:
      @QObject::killTimers: timers cannot be stopped from another thread@

      [/quote]

      Ok, I've found the problem:
      @
      parser.connect(&workThread, SIGNAL(started()), SLOT(start()));
      parser.connect(&workThread, SIGNAL(finished()), SLOT(stop()));
      @
      .. should be..
      @
      parser.connect(&workThread, SIGNAL(started()), SLOT(start()), Qt::QueuedConnection);
      parser.connect(&workThread, SIGNAL(finished()), SLOT(stop()), Qt::QueuedConnection);
      @
      Apparently, I have to explicitly specify the QueuedConnection, contrary to what the documentation says:
      [quote]
      Qt::AutoConnection (default) Same as DirectConnection, if the emitter and receiver are in the same thread. Same as QueuedConnection, if the emitter and receiver are in different threads
      [/quote]

      Maybe this is a bug? I'm using 4.7.1

      Anyway, I'm still wondering what's the correct way of using QThreads.

      o_o Sorry for my rusted english.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dangelog
        wrote on last edited by
        #3

        That doc line is wrong. It has been fixed in the latest snapshot, though.

        See also what I wrote in my article http://developer.qt.nokia.com/wiki/Threads_Events_QObjects#913fb94dd61f1a62fc809f8d842c3afa

        Software Engineer
        KDAB (UK) Ltd., a KDAB Group company

        1 Reply Last reply
        0
        • I Offline
          I Offline
          ivan.todorovich
          wrote on last edited by
          #4

          [quote author="peppe" date="1298995839"]That doc line is wrong. It has been fixed in the latest snapshot, though.

          See also what I wrote in my article http://developer.qt.nokia.com/wiki/Threads_Events_QObjects#913fb94dd61f1a62fc809f8d842c3afa[/quote]

          So I'm doing the things the right way.

          --

          I have another question though. Isn't there any way I could do something like this: (pseudo Qt code)

          @
          #include <QtGui/QApplication>
          #include "MainWindow.h"
          #include <QtDebug>

          #include <QThread>

          #include "CAbstractParser.h"

          int main(int argc, char *argv[])
          {

          QApplication a(argc, argv);
          MainWindow w;
          w.show();
          
          cLog->notice("==========================================");
          cLog->notice("STARTING UP...");
          cLog->notice("==========================================");
          
          QThread::run(work);
          
          return a.exec&#40;&#41;;
          

          }

          int work()
          {

          QThread t;
          
          // heavy startup [...]
          
          CAbstractParser parser("C:/Users/User/Desktop/test.log");
          parser.start();
          
          // AnotherWorkerClass work1;
          // work1.start();
          
          // AnotherWorkerClass work2;
          // work2.start();
          
          // ...
          
          return t.exec(&#41;;
          

          }
          @

          I know this isn't possible, but hopefully you'll get the idea.

          o_o Sorry for my rusted english.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            simonmeaden
            wrote on last edited by
            #5

            A good article on using threads in 4.4 is found here "How To Really, Truly Use QThreads; The Full Explanation":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ This helped me when I read it. I had been running around in circles like a headless chicken up till then.

            1 Reply Last reply
            0
            • R Offline
              R Offline
              RaubTieR
              wrote on last edited by
              #6

              Hello. I think you can do like so:
              workerthread.hpp
              @//#your includes, and QThread
              class WorkerThread: public QThread
              {
              Q_OBJECT
              public:
              WorkerThread(/a pointer to an object
              that signals to worker
              /Caller* c)
              : m_Caller(c) // remember pointer to use in threadfunction
              { this->start(); } // start automatically, so you should only create an object
              ~WorkerThread()
              {
              this->exit(0); // ask main loop to quit
              this->wait(3000); // wait for thread to finish
              if(this->isRunning()) // if it failed to finish within 3 sec
              this->terminate(); // kill it with fire
              }

              void run() // yup the threadfunction by ourselves
              {
              m_Worker = new Worker(); // it should be created in threadfunction!
              connect(m_Caller, SIGNAL(...), m_Worker, SLOT(...),
              Qt::QueuedConnection);
              exec(); /* here event processing loop starts, as it is for QThread by default, but the difference we have objects connected */
              delete m_Worker; // works only after exit() call when main loop ends
              }

              private:
              Worker* m_Worker; // pointer to worker object
              Caller *m_Caller; // pointer to caller object
              }@

              You should remember that QThread object itself is not a thread, but only handler and it exists in parent thread.
              Also if you have strong thread-sync requirement, you can apply some sync objects like QSemaphore to make sure that objects are connected when you first time signal an event (is simple, i can show if needed).

              1 Reply Last reply
              0
              • S Offline
                S Offline
                simonmeaden
                wrote on last edited by
                #7

                The general opinion now seems to be that you should not be extending QThread but write all your code in a worker object then pass it to a thread using the moveToThread method. These two articles are the best that I have found are a blog by Bradley Hughes "You're doing it wrong":http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ and this which I think explains it betterb"How To Really, Truly Use QThreads; The Full Explanation":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/.

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

                  Hi all, I've formally opened a ticket for this old old issue in https://bugreports.qt-project.org/browse/QTBUG-26899

                  I just found out that the community can submit patches for the Qt docs too. Perhaps we can collaboratively write up a better example for QThread usage?

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

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    astodolski
                    wrote on last edited by
                    #9

                    [quote author="JKSH" date="1345632260"]Hi all, I've formally opened a ticket for this old old issue in https://bugreports.qt-project.org/browse/QTBUG-26899

                    I just found out that the community can submit patches for the Qt docs too. Perhaps we can collaboratively write up a better example for QThread usage?[/quote]

                    That would be nice. So much is representative of the former way.

                    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