5

I will keep the code simple so that you guys can see what I'm trying to do ;) I am aware of all of the locking issues, etc. I'm trying to figure out how signals and slots play with threads.

In main.cpp:

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyConsole c;       // Subclasses QThread and implements run()
    MyReceiver r(app); // We pass app to MyReceiver for later (see below)
    QObject::connect(&c, SIGNAL(sendit()),
                     &r, SLOT(gotit()));
    c.start();         // Start the worker thread
    app.exec();
}

Assume that the signals and slots were properly set up in the header files (I've tested and they are). Now, here's the issue:

In MyReceiver.cpp:

void MyReceiver::gotit()
{
    QLabel *label = new QLabel(0, "Hello");  // Some GUI element, any will do
    app.setMainWidget(*label);               // Some GUI action, any will do
}

The question is: Because the MyReceiver object was created in main(), which is on the main thread, does that mean that the slots (e.g., gotit()) will run on the main thread and are therefore safe for doing GUI stuff? Even in cases where the signal was raised from a different QThread (like MyConsole in this example)?

Is there a better way to allow worker threads to interact with the GUI (for example, Obj-C/Cocoa have a "send message on main thread" type of approach). What is "The Qt way" of doing this?

Thanks in advance!

Badmanchild
  • 990
  • 9
  • 18

2 Answers2

5

By default (Qt::AutoConnection), slots will run in the thread the QObject was created in. So, no matter from what thread you emit the signal, the slot will be run always in the thread, the QObject "lives" in (if a Qt event loop is running in that thread, otherwise the event can't be delivered). Since the main thread will become the Qt GUI thread, this will work as expected. This is indeed the Qt way of interacting with the GUI. See also: http://doc.qt.nokia.com/4.7/thread-basics.html (look for thread affinity).

awx
  • 126
  • 1
  • 4
  • "no matter from what thread you emit the signal, the slot will be run always in the same thread" this sentence is a bit ambuigous, it sounds like the slot will always be run in the same thread the signal was emitted from. I know that you don't mean it this way (as the rest of your answer is correct), but it may confuse others. – Christian Rau Aug 26 '11 at 22:25
  • 1
    ok, that was ambiguous, I've rephrashed that. thanks for the comment. – awx Aug 26 '11 at 22:34
  • Should be noted that you can still send signals even without the exec loops running. Just call `QCoreApplication::processEvents()` periodically and it will for all intended purposes be like you have exec loops running. This is great for situations where you cannot give control of the loop back to the OS but still need the inputs/outputs of signals from different threads. – g19fanatic Jan 16 '13 at 12:55
  • Correct. `QCoreApplication::processEvents()` is more a workaround for long running operations and makes little sense without event loops (it processes only events on the calling thread), though. – awx Feb 28 '13 at 13:54
2

The "Qt way" to emit a signal from one thread and receive it in a different thread is to use a Queued connection

connect( obj, SIGNAL(foo()), other_obj, SLOT(bar()), Qt::QueuedConnection )

From the Qt documentation for Qt::QueuedConnection:

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

Chris
  • 17,119
  • 5
  • 57
  • 60