[Solved] Emitting Qt signals from threads other than the Main Qt GUI Thread.
-
Hello Qters! :D
First of all, I want to apologise if what I am going to ask here is already discussed or covered in the Qt documentation. I found people saying different things and I am a little bit confused.
My question is about how Qt handles signals when they are emitted from a Thread (other than the main Qt GUI thread).
Here is my situation:
I have my "MainWindow" class which inherits from a QMainWindow. Then I fire up a thread "ThreadA" through the QMainWindow constructor or through a QMenu QAction (ie: through the main Qt GUI thread, right?).
For now, let's say that my Thread does not inherit from a QThread. So, I use the Q_OBJECT macro to allow it to emit signals.
What I want to do now is to connect a signal emitted from "ThreadA" to a slot of "MainWindow". And when I emit the signal from threadA, I want the slot() to be called from the Qt GUI thread.- Where should I make the connection (ie: call connect() function)? On the Main Qt GUI thread? Or on "ThreadA"?
- When I emit the signal, on which thread the slot() will run? Qt GUI thread or "ThreadA"?
- I read that if the signal is emitted from a thread that is different from the thread the object of the slot belongs(let's call it "parent thread"), then the connection will be a "queued connection" and the slot will be executed later from that "parent thread").
Is this true/guaranteed? - How Qt knows who is the "parent thread" of the slot?
- And in my case, how it will be queued for execution in the GUI thread? In the form of an event?
- I also read that the above is only possible if the Thread is a QThread. Otherwise Qt can not figure out that the signal is emitted from an other thread. Is this true?
- Some people say that if I don't have a QThread, I should explicitly define the connection as queued connection. This this a hack? Or it is guaranteed that it will work?
Most of the things above work as described but I am not sure if these are guaranteed behaviours or hacks that happened to work. Thanks a lot for your time guys and I am sorry if I asked a lot of silly questions.
Cheers!
-
bq. Where should I make the connection (ie: call connect() function)? On the Main Qt GUI thread? Or on “ThreadA”?
Does not matter, QObject::connect() is thread-safe, as the documentation states.
bq. When I emit the signal, on which thread the slot() will run? Qt GUI thread or “ThreadA”?
The slot will be executed in the thread of the receiver. Since the receiver is MainWindow, that would be the GUI thread.
bq. I read that if the signal is emitted from a thread that is different from the thread the object of the slot belongs(let’s call it “parent thread”), then the connection will be a “queued connection” and the slot will be executed later from that “parent thread”).
Is this true/guaranteed?Yes, that is guaranteed if you use auto connections (the default). When emitting a signal and the emitter is in a different thread than the receiver, Qt will always post an event to the receiver's event loop, and the slot will be executed during the next event processing.
If you explicitly call connect() with the type DirectConnection, then the slot is executed in the emitter's thread.bq. How Qt knows who is the “parent thread” of the slot?
Well, there is QObject::thread(), I assume the internal code uses that to find the thread of the receiver object.
bq. And in my case, how it will be queued for execution in the GUI thread? In the form of an event?
Yes, Qt will use an event for that. Internally, that is a QMetaCallEvent, which you can see in queued_activate() in qobject.cpp if you are interested in the implementation.
bq. I also read that the above is only possible if the Thread is a QThread. Otherwise Qt can not figure out that the signal is emitted from an other thread. Is this true?
bq. Some people say that if I don’t have a QThread, I should explicitly define the connection as queued connection. This this a hack? Or it is guaranteed that it will work?
Hmm, I don't know. I guess what they mean here is that the thread was not created by Qt, but with some other implementation like boost threads or pthreads. I don't know about that case.
Maybe you meant this: If your object doesn't derive from QThread, but from QObject, that is fine, as long as the object was created in the correct thread, i.e. in QThread::run(), or was moved to the correct thread later with moveToThread().