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?
QtWS25 Last Chance

What's the correct way of using QThread?

Scheduled Pinned Locked Moved General and Desktop
9 Posts 6 Posters 8.9k 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.
  • 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