Talking to Qt Threads

I wrote about multi-threading in Qt a while back, and how to use QThread to wrap a blocking function call “lock free”. Today we’ll talk about how to pass data into your thread. This approach can be used, for example, to tell your QThread to stop.

There are two ways to use QThread, with and without an event loop, and the preferred method for talking to a QThread depends on which of them you use.

Way 1: Without an event loop

When you’re not using an event loop, the thread’s run() method often looks like this:

void MyThread::run()
{
    forever
    {
        // Do some stuff
    }
}

Since this method does not use an event loop, there is no way to deliver a signal to your thread. So if you want to pass data into the thread, you have to use a good old fashioned mutex. Let’s look at an example showing you how to stop your thread:

void MyThread::run()
{
    forever
    {
        {
            // "mutex" and "stopRequested" are member
            // variables of MyThread:
            QMutexLocker locker(&mutex);
            if(stopRequested)
                return;
        }
        
        // Do some stuff
    }
}

void MyThread::stop()
{
    QMutexLocker locker(&mutex);
    stopRequested = true;
}

In this case, we have to check the stopRequested variable in a timely manner in our thread’s run() method. The longer you run between checks, the longer it will take your thread to actually stop.

Outside observers can use the finished() signal to know when your thread is actually done. So if you are in a QMainWindow, for example, and a closeEvent() happens, you can ignore the event, call MyThread::stop(), and then when the QThread::finished() signal arrives, you can actually close the window.

The downside is that the stop() call will actually block while it tries to acquire the mutex. Given the way this code is written, the blocking will probably be very short, but hey, I hate blocking. Let’s see if we can dig up a better way to do this.

Way 2: With an event loop

If you have an event loop, you can use Qt’s meta-objects to talk to your thread. Let’s look at the same example as before, only this time with no locking or blocking.

void MyThread::MyThread()
{
    moveToThread(this);
}

void MyThread::run()
{
    QTimer *timer = new QTimer();
    connect(timer, SIGNAL(timeout()),
        this, SLOT(doSomething()));
    timer->start(0);

    exec(); // starts the event loop, and doesn't
            // return until it is told to quit()
}

void MyThread::stop()
{
    if(currentThread() != this)
    {
        // The caller is running in a
        // different thread, so use Qt to
        // call stop() later, on our own thread:
        QMetaObject::invokeMethod(this, "stop",
                        Qt::QueuedConnection);
    }
    else
    {
        // Now the call has arrived from our
        // own thread, yay! We can safely
        // shut down our event loop.
        quit();
    }
}

Look mom! No locks! Now we have killed our thread, safely and gracefully. There is no chance of blocking, and we learned something about QMetaObject.

A couple items to note:

  • The doSomething() method is left as an exercise for the reader, but be careful about the QTimer interval. I used 0, which means it will be firing almost constantly.
  • The stop() method must be a slot in MyThread (and not just a regular method) or else invokeMethod() will return false and not actually re-invoke stop() for you.
  • You can pass arguments to your thread this way, but it requires a bit more fun with QMetaObject::invokeMethod().
  • You can reduce this whole thing to a magical macro that you could put at the top of your stop() method, saving you from having to write if(currentThread() == this) at the top of every method. Hint: use the __FUNCTION__ macro.
  • To run this example code, you’ll need to #include these files: QThread, QTimer, QMetaObject, QMutexLocker, and QMutex
  • To call quit(), it may not actually be necessary to be running on the same QThread (it works for me without the QMetaObject), but this will be required when you start passing in data to your thread. Without it, your program could do unpredictable naughty things. I can’t find anything in the docs about whether quit() is thread safe.

I’ve found this QMetaObject approach the most effective and easiest way to pass data to QThreads safely, without blocking and without locks.

Happy threading!

23 comments to “Talking to Qt Threads”

You can leave a reply or Trackback this post.
  1. I want to write a macro for this QMetaObject::invoke trick, since I’m using it in a few places, but I want it to work in slots that also have parameters.

    These are non variadic methods tho, don’t know how to get a list of pointers to passed arguments.

    Using the following, i can get a list of parameter type strings (needed for QGenericArgument), but i’m missing the param values. Any ideas?

    QString qfi( Q_FUNC_INFO );
    Q_ASSERT( qfi.startsWith(“void “) );
    int methid = metaObject()->indexOfSlot( qfi.remove(0, qfi.indexOf(“::”)+2 ) );
    Q_ASSERT( methid != -1 ); // must be a slot, not just a method
    QMetaMethod mm = metaObject()->method( methid );

    qDebug()<< mm.signature()
    << "index:" << methid
    << "ParamNames: " << mm.parameterNames()
    << "paramtypes: " << mm.parameterTypes();

  2. RJ: Great question. I actually wrote a macro a while back. I’ll post a comment here when I get home tonight to explain the missing parts. Maybe I’ll write a new blog post just about the macro method.

  3. RJ: Here’s an example macro that you can place within slots to make them thread safe:

    // Just a helper macro:
    #define NO_RETURN_VALUE
    
    // This does the real work:
    #define THREAD_MAGIC(targetThread, returnValue, args)     \
        if(QThread::currentThread() != targetThread)                     \
        {                                                                \
            QString slotName = __FUNCTION__;                             \
            slotName.remove(QRegExp("^.*::"));                           \
            bool ret = metaObject()->invokeMethod(this,                  \
                    qPrintable(slotName), Qt::QueuedConnection,          \
                    args.count() >=  1 ? args[0] : QGenericArgument(0),  \
                    args.count() >=  2 ? args[1] : QGenericArgument(0),  \
                    args.count() >=  3 ? args[2] : QGenericArgument(0),  \
                    args.count() >=  4 ? args[3] : QGenericArgument(0),  \
                    args.count() >=  5 ? args[4] : QGenericArgument(0),  \
                    args.count() >=  6 ? args[5] : QGenericArgument(0),  \
                    args.count() >=  7 ? args[6] : QGenericArgument(0),  \
                    args.count() >=  8 ? args[7] : QGenericArgument(0),  \
                    args.count() >=  9 ? args[8] : QGenericArgument(0),  \
                    args.count() >= 10 ? args[9] : QGenericArgument(0)); \
            if(!ret)                                                     \
            {                                                            \
                qFatal(qPrintable(__FUNCTION__ +                         \
                  QString(" Could not call QMetaObject::invokeMethod(). " \
                  "Check your argument list quantity and types.")));     \
            }                                                            \
            return returnValue;                                          \
         }        
    
    #define MAKE_THREAD_SAFE_0(TargetThread, returnValue)                \
            do {                                                         \
            QList<QGenericArgument> args;                                \
            THREAD_ME_LIKE_A_NEEDLE(TargetThread, returnValue, args);    \
            } while (0);                                                  \
    
    
    #define THREAD_MAGIC_1(TargetThread, returnValue, ArgType1, ArgName1)         \
            do {                                                         \
            QList<QGenericArgument> args = QList<QGenericArgument>() <<  \
                Q_ARG(ArgType1, ArgName1);                               \
            THREAD_MAGIC(TargetThread, returnValue, args);    \
            } while (0);              
                                                           \
    
    #define THREAD_MAGIC_2(TargetThread, returnValue, ArgType1, ArgName1, ArgType2, ArgName2) \
            do {                                                         \
            QList<QGenericArgument> args = QList<QGenericArgument>() <  \
                Q_ARG(ArgType1, ArgName1) < <                             \
                Q_ARG(ArgType2, ArgName2);                               \
            THREAD_MAGIC(TargetThread, returnValue, args);    \
            } while (0);                                                  \
    
    
    

    And now the usage in one of your slots:

    void MyThread::mySlot(const QString &name, int count)
    {
       THREAD_MAGIC_2(this, NO_RETURN_VALUE, QString, name, int, count);
    
      // You are now thread safe
    }
    

    Notice you can only use this with slots that have between 0 and 10 arguments, which is actually a limitation of Qt’s signal/slot system (if I recall correctly).

    Happy thread hacking!

  4. Well, it turns out I was wrong with this article. You don’t actually have to subclass QThread. You can just *use* one, as noted here:

    http://blog.exys.org/entries/2010/QThread_affinity.html

    Here’s a revised version:

    main.cpp:

    #include 
    #include 
    #include 
    
    class MyObject : public QObject
    {
        Q_OBJECT
    
        public:
            MyObject() : QObject(NULL)
            {
                moveToThread(&_thread);
                _thread.start();
            }
    
        public slots:
            void safelyDoSomething()
            {
                if(QThread::currentThread() != &_thread)
                {
                    qDebug() < < __FUNCTION__ << "Wrong thread";
                    QMetaObject::invokeMethod(this, "safelyDoSomething",
                            Qt::QueuedConnection);
                }
                else
                {
                    qDebug() << __FUNCTION__ << "Right thread";
                }
            }
    
        private:
            QThread _thread;
    };
    
    int main(int argc, char **argv)
    {
        QCoreApplication app(argc, argv);
    
        MyObject object;
        object.safelyDoSomething();
    
        return app.exec();
    }
    
    #include "main.moc"
    

  5. João Abecasis says: -#1

    QThread::quit is thread-safe.

  6. Hi Dave, I have been following the message threads associated with thread affinity, and the lack of necessity for deriving threads from QThread
    (per the article “You’re doing it wrong by Bradley Hughes” and Arvid Picciani’s article).

    I need to create a network thread separate from my UI thread.
    My Udp Thead has to be continuously operating and long lived.

    The UI thread will need to block while sending network content to another embedded board and retrieving content from the network in response to an outbound command. At the same time, the application will need to dispatch certain received UDP network packets to other threads in the application.

    I am considering an implementing that uses current best practices, and trying to reduce or eliminating locking where possible. The description of invokeMethod() parallels the behavior of the method of the same name under .NET, and I will use this techique where required.

    I will be using QUdpSocket for the network interface in what will be a separate thread from the UI thread. The Qt implementation of QUdpSocket can be used in asynchronous mode, where signals are issued upon reception of network data, or in blocking mode which is suitable only for use within a separate thread.

    So my questions boils down to this.

    Assuming I use the thread method described by Arvid Picciani, does this necessitate either the asynch or blocking mode of QUdpSocket? If I were to directly derive from QThread, my run() implementation in the thread would call exec() to start the event loop in the thread. This would be for the asynch mode of QUdpSocket which requires an event loop, and I assume the thread would pend until data was received. Perhaps, I could also use the blocking method here as well, but the exec() call would remain to allow for signals and slots to operate.

    When using the technique described by Arvid Picciani, where I do not write a run() method, but instead have a QThread in my class, call start() on it, and call moveToThread(&thread), does this implement that a default
    implementation calling the thread’s event loop will be in place?

    How would a long lived thread be implementing using the Arvid Picciani technique.

  7. You asked a lot of questions, so I’ll try to a answer at least one of them.

    To implement a long lived thread using Arvid’s technique, just allocate the QThread on the heap with new. It really is that simple.

  8. Thanks Dave, my questions could be more focused. In a nutshell, using this technique, I assume I would call exec() in my “doWork” slot similar to calling exec() in the Run() method of QThread? Do I have this correct? There is a broad discussoin on this technique in the Qt circles, and the fact that the Qt documentation does not do a good job of indicating that this technique is preferred over derivations from QThread. Have you changed over to this technique as part of your best practice?

  9. Bob,

    I have not yet adopted the “you’re doing it wrong” sublcass avoidance in my QThread code. I am still sub-classing QThread. However, it seems that in order to call exec() (which is a blocking call for the life of the event loop you are creating), you *must* sub-class QThread, reimplement the run() method, and call exec() in your run() method.

    I don’t see any way around sub-classing QThread if you want your thread to have an event loop.

    Now, you only *need* an event loop if you are receiving signals, and not necessarily if you are only emitting them (double check me on that though). However, many classes require an event loop to function properly. It’s likely QUdpSocket will need an event loop running in order for it to function properly.

    You really should experiment with this though, as I haven’t done it (yet).

    –Dave

  10. Woops! Ignore my last comment. The default QThread implementation of the run() method actually *does* call exec(). So all you have to do is this:

    QThread *myUdpThread = new QThread();
    myUdpThread->start();

    QUdpSocket *socket = new QUdpSocket();
    socket->moveToThread(myUdpThread);

    connect(socket, SIGNAL(readyRead()), …

    And that should move all UDP socket processing to the separate thread, and you can reveive its signals from your main thread (if that’s what you want).

    If you want to handle the data read from the socket in the separate thread, you’ll have to do something like this:

    class MyDataProcessor : public QObject {
    Q_OBJECT
    public slots:
    void readyRead() {
    // do something here
    }
    };

    MyDataProcessor *processor = new MyDataProcessor();
    processor->moveToThread(myUdpThread);

    connect(socket, SIGNAL(readyRead()), processor, SLOT(readyRead()));

    –Dave

  11. Thanks again for your effort Dave, and your contributions to the broader Qt community. I will give this a try and let you know my results.

    I have read the many comments on the “your doing it wrong” thread, and there seems to be varying opinions, perhaps some not too happy to learn they are not using what is considered best practices — but I do not see a consensus.

    One sort of unique requirement that I have is that I actually need to block my UI thread while it is retrieving data (or a timeout occurs of 300 ms), while the UDP dispatcher, presumably in another thread, feeds content to other worker threads. Where I need some clarity is perhaps understanding more the nature of the QUdpSocket implementation under the covers. I think it safe to say that if it is being used in asynch mode, then an event loop would be absolutely necessary. I would also want to take advantage of the thread safe signalling using invokeMethod() as you have described in your blog.

    I am not as sure of this requirement when it is being used in blocking mode. There is a suggestion from what I have read on QUdpSocket that perhaps QUdpSocket operates in its own thread already, but I can not ascertain that from casually looking at the Qt source code.

  12. Bob,

    In the 10+ years I’ve been designing user interfaces, I have *never* seen a good reason to block the event loop like that. That seems like a mis-requirement. It’s one thing to prevent user input for a period of time, but blocking the event loop is something altogether different, and ill-advised in my opinion.

    It is *highly* unlikely that QUdpSocket uses multi-threading under the hood. It probably uses non-blocking socket I/O.

    –Dave

  13. Hi Dave,

    Let me clarify why the UI needs to act blocking (but perhaps not actually be blocking). The UI presents a view of content from a separate embedded board. What is displayed in the UI represents a view upon data on the embedded board that is shared over a network connection.

    The content of the GUI will be dynamic, such that when the user picks a particular GUI screen element, a volley of UDP messages with the embedded board will occur to define what will be made visible on the next displayed screen.

    My application acts to a large extent like a modern cellphone driving purely by a touchscreen under embedded Linxu (e.g. kinectic scrolling lists, icon views, multiline list controls, swipe navigation, etc.) As such, there are 4 off touchscreen buttons that the user could press, their is a popup context menu when the user can make selectoins, etc. While the volley is occurring, all user navigation needs to be prohibited.

    But your response has me thinking, that maybe there is a better way to a act blocking, without actually blocking the event loop of the GUI thread.

    Perhaps I can find a convenient way of setting some form of flag or signal or semaphore that would be set when an outstanding communications session is underway, and block all user activity (or perhaps queue it) while this is occurring. If you have some thoughts on this type of implementation, I would be interested.

    I always believe in the KISS principle (Keep it simple stupid), and perhaps I am making it more complex than it warrants.

  14. Hey Dave, quick and short question. When implementing threading using the “approved” technique, and having the default thread run() method executing the thread event loop, is it your understanding that the thread will pend waiting on some activity, such as the reception of a signal()? I want to make sure that threads are not burning processor time unless necessary. I don’t know enough about the event loop to make this accessment. Also, feel free to clean out my comments if you want to remove some of my junk from your blog.

  15. Bob, have you not tried to measure the CPU usage?

  16. My understanding from others in the Qt Centre forums is that exec() may/will not pend/block. Perhaps this is intuitive as how can a thread process events without having the event loop actually running. From my understanding, a thread WITHOUT an event loop can signal (sender) a thread with a slot corresponding to the signal (receiver) WITH an event loop, but the receiver must be running exec() to receive the signal.

    With this in mind, I intend to have secondary threads NOT running an event loop so they will pend when not performing useful work. The secondary threads will signal the main GUI thread which is running and event loop via a signal. The secondary threads may communicate with each other, perhaps send heap allocated messages to other threads not running an event loop, but in this case, will not use the signal method.

  17. i think you would like to include this in your tutorial – for beginners
    #include
    #include
    #include

  18. MyLibraryWrapper
    MyLibraryWrapper

    MyLibraryWrapper

    #include \
    #include \
    #include \

  19. Hi ,
    Please read my query below..

    i want to Create some threads, and want to interrupt them with another thread.
    i have seen some videos where they are keep on checking for a flag to become true, then they are simply saying break/quit;

    But in my case i don’t have to write any loops but i have few statements which download a file from net. so i want to stop downloading in between @ some time.

    CAN ANY BODY HELP ME IN THIS REGARDING?

  20. Suresh,

    Just use signals and slots with connect() and Qt::QueuedConnection. That’s what Qt::QueuedConnection is for, sending messages from one thread to another. Have you read the QThread docs?

    –Dave

  21. Hi,
    this is regarding, in multi threading environment, where GUI thread will be handling , all GUI events. if i use a timer event for regular updations of GUI, timer event and slot connected with it, my doubt is , which thread will run the slot the definition, whether GUI thread or any other thread.
    please clarify me.

    rams

  22. rams: The connected slots are processed by the thread that owns given QObject. It’s the thread given by QObject::thread().

  23. rams: I think it depends on the type of connection you pass to QObject::connect(). QueuedConnection, DirectConnection, or AutoConnection. Docs here: http://qt-project.org/doc/qt-5.1/qtcore/qt.html#ConnectionType-enum

Write a Reply or Comment

Your email address will not be published.