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. Updating QThread docs (finally!)
Forum Updated to NodeBB v4.3 + New Features

Updating QThread docs (finally!)

Scheduled Pinned Locked Moved General and Desktop
25 Posts 6 Posters 14.8k 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

    Ok, they're calling for "community participation in polishing Qt5 docs":http://community.kde.org/Qt5/Documentation , which is a great chance to finally update the archaic QThread examples.

    I thought I'd get the ball rolling by updating the Detailed Description of the QThread class ref -- The previous version and Andre's doc notes (which I've incorporated) are at http://qt-project.org/doc/qt-5.0/qthread.html

    Here's my draft; what does everyone think? Should anything be added/changed/removed?

    =============================================================
    DRAFT STARTS (Will be edited as we go)
    Note: If headings look weird in the future, it's 'cos they fixed "this forum bug":https://bugreports.qt-project.org/browse/QTWEBSITE-468

    h3. Detailed Description

    The QThread class provides a platform-independent way to manage threads.

    A QThread object manages one thread of control within the program. To make code run in a separate thread, simply create a QThread, change the thread affinity of the QObject(s) that contain the code, and start() the new event loop. For example:
    @
    class Worker : public QObject
    {
    Q_OBJECT

    public slots:
    void doWork() {
    ...
    }
    };

    void MyObject::putWorkerInAThread()
    {
    Worker *worker = new Worker;
    QThread *workerThread = new QThread(this);

    connect(workerThread, &QThread::started, worker, &Worker::doWork);
    connect(workerThread, &QThread::finished, worker, &Worker::deleteLater);
    worker->moveToThread(workerThread);
    
    // Starts an event loop, and emits workerThread->started()
    workerThread->start(); 
    

    }
    @

    The code inside the Worker's slot would then execute in a separate thread. In this example, the QThread triggers the Worker's doWork() slot upon starting, and frees the Worker's memory upon terminating. However, you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections.

    Note: If you interact with an object, using any technique other than queued signal/slot connections (e.g. direct function calls), then the usual multithreading precautions need to be taken.

    Note: It is not possible to change the thread affinity of GUI objects; they must remain in the main thread.

    h2. Managing threads

    QThread will notify you via a signal when the thread is started(), finished(), and terminated(), or you can use isFinished() and isRunning() to query the state of the thread.

    You can stop the thread by calling exit() or quit(). In extreme cases, you may want to forcibly terminate() an executing thread. However, doing so is dangerous and discouraged. Please read the documentation for terminate() and setTerminationEnabled() for detailed information.

    From Qt 4.8 onwards, it is possible to deallocate objects that live in a thread that has just finished(), by connecting that signal to QObject::deleteLater().

    Use wait() to block the calling thread, until the other thread has finished execution (or until a specified time has passed).

    QThread also provides static, platform independent sleep functions: sleep(), msleep(), and usleep() allow full second, millisecond, and microsecond resolution respectively. These functions were made public in Qt 5.0.

    Note: wait() and the sleep() functions should be unnecessary in general, since Qt is an event-driven framework. Instead of wait(), consider listening for the finished() signal. Instead of the sleep() functions, consider using QTimer.

    The static functions currentThreadId() and currentThread() return identifiers for the currently executing thread. The former returns a platform specific ID for the thread; the latter returns a QThread pointer.

    h2. Subclassing QThread

    Subclassing QThread is unnecessary for most purposes, since QThread provides fully-functional thread management capabilities. Nonetheless, QThread can be subclassed if you wish to implement advanced thread management. This is done by adding new member functions to the subclass, and/or by reimplementing run(). QThread's run() function is analogous to an application's main() function -- it is executed when the thread is started, and the thread will end when it returns.

    Note: Prior to Qt 4.4, the only way to use QThread for parallel processing was to subclass it and implement the processing code inside run(). This approach is now considered bad practice; a QThread should only manage a thread, not process data.

    If you require event handling and signal/slot connections to work in your thread, and if you reimplement run(), you must explicitly call exec() at the end of your reimplementation:
    @
    class AdvancedThreadManager : public QThread
    {
    protected:
    void run()
    {
    /* ... other code to initialize thread... */

        // Begin event handling
        exec();
    }
    

    };
    @

    It is important to remember that a QThread object usually lives in the thread where it was created, not in the thread that it manages. This oft-overlooked detail means that a QThread's slots will be executed in the context of its home thread, not in the context of the thread it is managing. For this reason, implementing new slots in a QThread subclass is error-prone and discouraged.

    See also Thread Support in Qt, QThreadStorage, QMutex, QSemaphore, QWaitCondition, Mandelbrot Example, Semaphores Example, and Wait Conditions Example.

    =============================================================
    DRAFT ENDS

    _Member function docs are on "Page 2":https://qt-project.org/forums/viewthread/20691/P15/ _

    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
      andre
      wrote on last edited by
      #2

      First of all: I think it is great that you want to work on improving the QThread documentation. Thanks!

      I think it would be better to simplify the example a bit more. You don't really need a supervisor object. The docnotes for the online documentation, the wiki and many other sources contain examples on how to do this with only the worker object and the QThread instance. Also, the example you give creates three objects without parent, and then looses the pointers to them. That will cause memory leaks, and we should not promote that. The QThread could be created with this as the parent, while the worker object could be deleted with deleteLater on thread termination.

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

        Thanks for your encouragement and advice, Andre :) Ok, example updated, and a short explanation for memory management added. Is this better?

        Also, should there still be some information in the Detailed Description on how to (appropriately) subclass QThread? Or would it be enough to have the info in the function description for QThread::run()?

        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
          andre
          wrote on last edited by
          #4

          I think the simplest code example is something like this:

          @
          class Worker : public QObject
          {
          Q_OBJECT

          public slots:
          void doWork() {
          ...
          }
          };

          void MyObject::putWorkerInAThread()
          {
          Worker *worker = new Worker;
          QThread *workerThread = new QThread(this);

          connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()));
          connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
          
          worker->moveToThread(workerThread);
          workerThread->start();
          

          }
          @

          And, yes, I think there should be something about the proper use of subclassing QThread in the detailed section of the QThread docs. It should explicitly warn against adding signals and slots there though.

          I think you added:
          [quote]
          Each thread gets its own stack from the operating system. The operating system also determines the default size of the stack. You can use setStackSize() to set a custom stack size.[/quote]
          I'm not sure how relevant this is. I think this belongs in the setStackSize() method itself. It is not a main feature, and not used all that often I think.

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

            [quote author="Andre" date="1348740754"]I think the simplest code example is something like this:[/quote]Thanks; updated, along with the explanation just below the code.

            [quote author="Andre" date="1348740754"]And, yes, I think there should be something about the proper use of subclassing QThread in the detailed section of the QThread docs. It should explicitly warn against adding signals and slots there though.[/quote] Do you mean discourage making connections from within the subclassed QThread object? Or discourage adding new signals/slots to the QThread subclass? What's the reason?

            The only warnings I can think of regarding subclassing, are:

            • A QThread is not meant to "be" the actual code that runs in another thread
            • A QThread should not be set as a parent of an object that's constructed inside its own implementation of run(), as they'll have different thread affinities
            • To ensure that an event loop is created (thus ensure that event handling and signals/slots are enabled for objects in the thread), the reimplemented run() must call exec() at the end

            Are these correct?

            [quote author="Andre" date="1348740754"]
            I'm not sure how relevant this is. I think this belongs in the setStackSize() method itself. It is not a main feature, and not used all that often I think.[/quote]Those lines were in the latest snapshot. I've removed them now.

            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
              andre
              wrote on last edited by
              #6

              [quote author="JKSH" date="1348744139"]Do you mean discourage making connections from within the subclassed QThread object? Or discourage adding new signals/slots to the QThread subclass? What's the reason?

              The only warnings I can think of regarding subclassing, are:

              • A QThread is not meant to "be" the actual code that runs in another thread
              • A QThread should not be set as a parent of an object that's constructed inside its own implementation of run(), as they'll have different thread affinities
              • To ensure that an event loop is created (thus ensure that event handling and signals/slots are enabled for objects in the thread), the reimplemented run() must call exec() at the end

              Are these correct?
              [/quote]

              I was refering to discouraging adding new slots and signals to the QThread subclass. The problem is, that these almost never end up doing what the deverloper intends. Usually, these slots or signals are used to keep tabs on progress or some other state of the threaded process, or to give input to that threaded progress. However, with the slots and signals being on the QThread subclass itself, and the QThread subclass instance living in the main thread, we have a problem. Slots are invoked in the context of the main thread, and not in the context of the thread that is actually managed by the object. Signals may work though.

              If you know what you are doing, then the above may be fine for your situation. But only if you understand the consequences. Judging by the posts on this forum and in other channels: people don't understand these consequences.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Beacon11
                wrote on last edited by
                #7

                Oh man, great call. As someone who only recently figured out how to properly use QThreads, this will be a godsend for lots of people.

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

                  @Andre:
                  Very enlightening observations, thank you for sharing them. I'll work out how to weave it into the body of the text, and update this thread (no pun intended)

                  @Beacon11:
                  Glad to hear that you worked it out :) Would you mind sharing what difficulties you faced, and what kind of information was most helpful to you?

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

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    Beacon11
                    wrote on last edited by
                    #9

                    [quote author="JKSH" date="1348757707"]@Beacon11:
                    Glad to hear that you worked it out :) Would you mind sharing what difficulties you faced, and what kind of information was most helpful to you?[/quote]

                    I followed the docs! I always subclassed QThread, and it always got messy. One day I decided there had to be a better way, and came across http://blog.qt.digia.com/2006/12/04/threading-without-the-headache/ . If that was just in the docs I would have never started down the subclassing road. Your doc update will be a simplified version of that blog post, which will be very helpful to those wanting to learn how to do it right.

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

                      Hi all, new text added:

                      • Big spiel on subclassing QThread
                      • Remind developers that basic multithreading precautions may still be needed

                      Any critique would be much appreciated!

                      @Beacon11: It is unfortunate that docs continued to advocate subclassing for years after the approach became unnecessary. Well, that's the purpose for this project: To help developers get it right the first time. If there's anything else you feel should be in the docs, please let me know!

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

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

                        I've just added subheadings and re-worded bits and pieces for improved clarity. I think that covers all the common and important use cases, but does anyone have any more suggestions? (be it for content, structure, or expressions)

                        In the meantime, I'll start working on the member function documentation.

                        Questions

                        • Does a QThread subclass need the Q_OBJECT macro, to start an event loop?
                        • For QThread::sleep(), the docs says "Forces the current thread to sleep for secs seconds." Is this correct? I'm wondering if it forces the thread being managed to sleep, not the current thread (which can be the thread that the QThread object lives in, depending on where sleep() is called)

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

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

                          Many thanks for your efforts!

                          [quote author="JKSH" date="1348894702"]I've just added subheadings and re-worded bits and pieces for improved clarity. I think that covers all the common and important use cases, but does anyone have any more suggestions? (be it for content, structure, or expressions)

                          In the meantime, I'll start working on the member function documentation.

                          Questions

                          • Does a QThread subclass need the Q_OBJECT macro, to start an event loop?
                            [/quote]

                          No. Q_OBJECT has the usual purposes (adding signals, slots (beware!), tr(), qobject_cast, etc.).

                          [quote]

                          • For QThread::sleep(), the docs says "Forces the current thread to sleep for secs seconds." Is this correct? I'm wondering if it forces the thread being managed to sleep, not the current thread (which can be the thread that the QThread object lives in, depending on where sleep() is called)[/quote]

                          It's correct -- it's a static member. You don't call it on a object (and it would make no sense to call aQThreadObject->sleep(10) and have an arbitrary thread blocked for 10 seconds); the thread that invokes that method is the one who sleeps.

                          Note that in 4.x those functions were protected, now they're finally public.

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

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

                            @peppe: You're welcome, and thanks for your clarifications too. I can't believe I didn't notice the 'static' modifier!

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

                            1 Reply Last reply
                            0
                            • napajejenunedk0N Offline
                              napajejenunedk0N Offline
                              napajejenunedk0
                              wrote on last edited by
                              #14

                              Guys, is it necessary to include the following qmake statement:
                              @
                              CONFIG += thread
                              @

                              or

                              @
                              CONFIG *= thread
                              @

                              ... when creating other threads?

                              The "thread":http://qt-project.org/doc/qt-4.8/qmake-variable-reference.html#config CONFIG variable's member does the following as stated by the qmake variable reference:

                              bq. The target is a multi-threaded application or library. The proper defines and compiler flags will automatically be added to the project.

                              As far as I can see by:
                              @
                              message($$CONFIG)
                              @

                              ... on Windows, the printed output contains:
                              @
                              thread_off
                              @

                              When I add:
                              @
                              CONFIG += thread
                              @

                              ... the CONFIG variable contains both "thread_off" and "thread".

                              Is it necessary to add this statement and if so, is the "thread_off" CONFIG member a standard one that, for instance, explicitly removes the helper utilities added by "thread"?

                              Is the following code correct:
                              @
                              CONFIG -= thread_off
                              CONFIG *= thread
                              @

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

                                Minor edit: Followed a suggestion by Quentin on the Development mailing list, and switched to Qt5-style signal-slot connections, to promote their use.

                                [quote author="napajejenunedk0" date="1348917475"]Guys, is it necessary to include the following qmake statement.... when creating other threads?[/quote] Hmm... I've never used that flag before, but my multithreaded Qt programs worked fine. If I'm not mistaken, multithreading support is already enabled by default since Qt 4.0.

                                By the way, you might get more responses if you start a new forum topic, with descriptive title that matches your question. It's also considered good etiquette to keep forum replies relevant to the original post; otherwise it makes it harder for others to find relevant information.

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

                                1 Reply Last reply
                                0
                                • napajejenunedk0N Offline
                                  napajejenunedk0N Offline
                                  napajejenunedk0
                                  wrote on last edited by
                                  #16

                                  Yes, I thought about posting a new forum thread before posting a response in this one. I will.

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

                                    Hi all, some more updates made, based on suggestions from the mailing list and this forum. Comments and suggestions would be appreciated, as usual.

                                    Changes:

                                    • Added fact: Connecting finished() to deleteLater() became possible in Qt 4.8
                                    • Added fact: sleep functions became public in Qt 5
                                    • Added: Member function documentation (below, due to length constraints. I think the drafts for other pages shall be going on the wiki :P)

                                    Questions:

                                    • QThread::event() currently has a blank doc entry; what do developers need to know about it? From the source code, it provides handling of quit events, on top of QObject::event(). Does this need to be published?

                                    =========================================================
                                    DRAFT STARTS
                                    Only modified member functions are shown: -Strikethroughs- = Deletions; Italics = Additions

                                    h3. Member Function Documentation

                                    h2. QThread::QThread(QObject * parent = 0)

                                    Constructs a new -thread with the given parent.- QThread to manage a new thread. The parent takes ownership of the QThread. The thread does not begin executing until start() is called.
                                    See also start().

                                    h2. QThread::~QThread()

                                    Destroys the -thread- QThread.

                                    Note that deleting a QThread object will not stop the execution of the thread it -represents- manages. Deleting a running QThread (i.e. isFinished() returns false) will probably result in a program crash. -You can wait() on a thread to make sure that it has finished.- Wait for the finished() signal before deleting the QThread.

                                    h2. QThread * QThread::currentThread() [static]

                                    Returns a pointer to a QThread which -represents- manages the currently executing thread.

                                    h2. void QThread::run() [virtual protected]

                                    The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec().

                                    You can reimplement -ed- this function to -do other useful work- facilitate advanced thread management. Returning from this method will end the execution of the thread.

                                    See also start() and wait().

                                    h2. void QThread::start(Priority priority = InheritPriority) [slot]

                                    Begins execution of the thread by calling run() -, which should be reimplemented in a QThread subclass to contain your code- . The operating system will schedule the thread according to the priority parameter. If the thread is already running, this function does nothing.

                                    The effect of the priority parameter is dependent on the operating system's scheduling policy. In particular, the priority will be ignored on systems that do not support thread priorities (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler for more details).

                                    See also run() and terminate().

                                    =========================================================
                                    DRAFT ENDS

                                    TODO:
                                    ~ Add version info for functions introduced in Qt 5
                                    ~ Add "\override" to QThread::event()
                                    ~ Give sleep(), msleep() and usleep() the same wording

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

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

                                      Random thoughts:

                                      • I wouldn't use the word "thread manager". I do understand what you try to stress, but a thread manager sounds more like an object managing more than one thread.
                                      • For event, just put \override without any further explaination.
                                      • "Every thread has its own stack." is a quite obvious statement to me... people failing to grasp thread basics probably shouldn't be playing with QThread at all
                                      • Instead of stressing that various sleep methods are public in 5.0, I would stress that their usage is very likely a symptom of bad programming :-P cf. http://qt-project.org/wiki/Threads_Events_QObjects#92dd35cc61ffc41d02defdcef071856d

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

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

                                        [quote author="peppe" date="1349024940"]

                                        • I wouldn't use the word "thread manager". I do understand what you try to stress, but a thread manager sounds more like an object managing more than one thread.[/quote]Good point. So "thread" implies that QThread IS-A thread, but "thread manager" implies a one-to-many relationship. What's a good alternative? I can think of:

                                        "[The constructor] constructs a new..."

                                        • "... thread controller."
                                        • "... thread control interface."
                                        • "... object that manages a thread."
                                        • "... QThread."
                                        • "... QThread that manages a new thread."
                                        • -"... QThread, along with the thread that it will manage."- Edit: Incorrect

                                        (Side note: Maybe the name of the class itself should be changed for the next version of Qt. But then again, people don't seem to struggle much when using QDir, which is-not-a dir)

                                        [quote author="peppe" date="1349024940"]

                                        • For event, just put \override without any further explaination.
                                        • "Every thread has its own stack." is a quite obvious statement to me... people failing to grasp thread basics probably shouldn't be playing with QThread at all[/quote]Done, and removed.

                                        [quote author="peppe" date="1349024940"]

                                        • Instead of stressing that various sleep methods are public in 5.0, I would stress that their usage is very likely a symptom of bad programming :-P cf. http://qt-project.org/wiki/Threads_Events_QObjects#92dd35cc61ffc41d02defdcef071856d[/quote]
                                          Good point. I've stressed that forced sleeps should be unnecessary given that Qt is an event-driven framework, and urged readers to consider QTimer instead for their needs. (Are there any other common reasons people force a thread to sleep? I've never actually used these functions myself)

                                        Continuing the train of thought, would you say that wait()-ing is sub-optimal, too? Personally, I listen for the finished() signal, and have never used wait().

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

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

                                          Updated, to encourage developers to listen for finished() instead of using wait(). Also edited the constructor/destructor descriptions.

                                          I'm planning to submit this to Gerrit in 48 hours, if there are no more comments from here or the mailing list. Thanks for all your input so far!

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

                                          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