Qt documentation states that signals and slots can be direct, queued and auto.

Cross Thread Signals and Slots. At emit time Qt compares thread ids. The id of the current thread calling emit signal. The id the receiver belongs to via obj-thread. If the threads are the same slots are called. If different an event is packaged/posted 47. Cross-thread signal-slot connections are implemented by dispatching a QMetaCallEvent to the target object.

  1. As QAbstractItemView uses AutoConnections, the signals will be queued if they are in another thread. So, AFAIU, the model and view must be in the same thread if things are not to break. It's not impossible that a model would try to insert and remove rows in quick succession.
  2. When the signal/slot is actually executed it is done in the receiver object's thread. Qt::AutoConnection (the default parameter) is a bit smarter. When a signal is emitted Qt checks the connection type, if it's an auto connection it checks the sender and receiver's thread affinity (the threads they live in).

It also stated that if object that owns slot ‘lives’ in a thread different from object that owns signal, emitting such signal will be like posting message – signal emit will return instantly and slot method will be called in target thread’s event loop.

Unfortunately, documentation do not specify that ‘lives’ stands for and no examples is available. I have tried the following code:

main.h:

Qt Cross Thread Signal Slot

main.cpp:

Output is:

MySlot() is never called :(. What I’m doing wrong?

Answers:

There are quite a few problems with your code :

  • like said by Evan the emit keyword is missing
  • all your objects live in the main thread, only the code in the run methods live in other threads, which means that the MySlot slot would be called in the main thread and I’m not sure that’s what you want
  • your slot will never be called since the main event loop will never been launched : your two calls to wait() will only timeout after a very long time (and you’ll probably kill your application before that happens) and I don’t think that’s what you want either, anyway they really have no use in your code.

This code would most likely work (though I have not tested it) and I think it does what you want it to do :

Now MyObject will live in thread2 (thanks to moveToThread).

MySignal should be sent from thread1 (thought I’m not sure on that one, it might be sent from main thread, it doesn’t really matter).

No event loop is needed in thread1 since emitting a signal doesn’t need an event loop. An event loop is needed in thread2 (lanched by exec()) to receive the signal.

MySlot will be called in thread2.

Answers:

Do not subclass QThread for Qt 4.4+

While Aiua’s answer is good, I want to point out some issues with QThread and Qt 4.6 or 4.7.

This article sums it up: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Lack of Documentation on Qt’s part

Unfortunately the problem stems from a lack of updates to documentation. Prior to Qt 4.4 QThread had no default run() implementation, which meant that you had to subclass QThread in order to use it.

If you’re using Qt 4.6 or 4.7 then you almost certainly should not subclass QThread.

Use moveToThread

The key to getting slots to execute in a worker thread is to use the moveToThread method as Aiua pointed out.

Tags: qt

Remarks

A few notes that are already mentioned in the official docs here and here:

  • If an object has a parent, it has to be in the same thread as the parent, i.e. it cannot be moved to a new thread, nor can you set a parent to an object if the parent and the object live in different threads
  • When an object is moved to a new thread, all of its children are also moved to the new thread
  • You can only push objects to a new thread. You cannot pull them to a new thread, i.e. you can only call moveToThread from the thread where the object is currently living in

Basic usage of QThread

QThread is a handle to a platform thread. It lets you manage the thread by monitoring its lifetime, and requesting that it finishes its work.

In most cases inhering from the class is not recommended. The default run method starts an event loop that can dispatch events to objects living in the class. Cross-thread signal-slot connections are implemented by dispatching a QMetaCallEvent to the target object.

A QObject instance can be moved to a thread, where it will process its events, such as timer events or slot/method calls.

To do work on a thread, first create your own worker class that derives from QObject. Then move it to the thread. The object can run its own code automatically e.g. by using QMetaObject::invokeMethod().

If your worker should be ephemeral and only exist while its work is being done, it's best to submit a functor or a thread-safe method for execution in the thread pool via QtConcurrent::run.

QtConcurrent Run

If you find managing QThreads and low-level primitives like mutexes or semaphores too complex, Qt Concurrent namespace is what you are looking for. It includes classes which allow more high-level thread management.

Let's look at Concurrent Run. QtConcurrent::run() allows to run function in a new thread. When would you like to use it? When you have some long operation and you don't want to create thread manually.

Now the code:

So things are simple: when we need to run another function in another thread, just call QtConcurrent::run, pass function and its parameters and that's it!

QFuture presents the result of our asynchronous computation. In case of QtConcurrent::run we can't cancel the function execution.

Invoking slots from other threads

When a Qt event loop is used to perform operations and a non-Qt-saavy user needs to interact with that event loop, writing the slot to handle regular invocations from another thread can simplify things for other users.

main.cpp:

OperationExecutioner.h:

OperationExecutioner.cpp:

Thread

Qt Signal Slot Example

OperationExecutioner.pro:

Qt Signal Thread