Why Do I Need DirectConnection & Potential Issues



  • In my application I have

    • A worker object with a slot DoWork()
    • A thread onto which I move my worker thread
    • A dialog window to whom the worker sends status updates

    The code looks something like this:

    QThread *pThread;
    MyWorker *pScriptProcessor;
    StatusDialog *statusDlg = new StatusDialog ();
    pThread = new QThread();
    pScriptProcessor = new MyWorker ();
    pScriptProcessor->moveToThread(pThread);
    connect(pScriptProcessor, & MyWorker::SendStatusUpdate, statusDlg, & StatusDialog::OnUpdate);//, Qt::DirectConnection);
    connect(this, &MyApp::SendStatusUpdate, statusDlg, & StatusDialog`::OnUpdate);
    connect(pThread, &QThread::started, pScriptProcessor, & MyWorker::DoWork);
    emit pThread->start();
    emit SendStatusUpdate(QString("hello"));
    

    The last emit put "hello" on my dialog. When I do the same from within MyWorker::DoWork it doesn't do anything. After reading up a lot, it seems this is because the signal and slot live in different threads, hence there is no DirectConnection but an event is posted but DoWork is blocking the event processing engine. This would also explain why it starts working when I don't push my worker on the thread (so the signal and slot are on the same thread) and when I define the connect as a DirectConnection.

    I still don't quite understand why this isn't working without DirectConnection, though. I assume, maybe incorrectly, that emit immediately posts an event to the receiver. The receiver is not blocked so it should be able to process the event. Or is emit not sending an event right away but instead also puts that into the message queue for sending the event later on?

    Also it is my understanding that with a DirectConnection the slot is executed in the thread that emitted the signal. Some of my slots are creating GUI elements like bitmaps and such. It is my understanding that those objects will be associated with the thread that created it, i.e. in this case my worker thread because my worker thread is executing the slot. Will this not cause issues or is my understanding incorrect, or is there an automatic mechanism to still associated such objects with the thread associated with the slot?

    Last but not least, I guess with the DirectConnection the call is blocking and I will get the result back immediately, rather than the slot having to send the result of the slot processing back.


  • Qt Champions 2016

    @qt27
    Hi,

    emit pThread->start();
    

    Start is not a signal, so this is not emit's place.

    When I do the same from within MyWorker::DoWork it doesn't do anything. After reading up a lot, it seems this is because the signal and slot live in different threads, hence there is no DirectConnection but an event is posted but DoWork is blocking the event processing engine.

    No. When you issue the emit the sender thread's event loop is of no consequence, the sender thread may have no event loop at all and it will still work. The receiver's thread, on the other hand, has to be running an event loop.

    Also it is my understanding that with a DirectConnection the slot is executed in the thread that emitted the signal.

    Yes, as with any direct function call, which is what Qt::DirectConnection is in practice. But that applies only in the sense Qt puts into QObject's thread affinity. If you leave Qt aside, an object cares not about threads, it's just a bunch of data stitched together. A method may be executed in a thread (i.e. it's stack frame be opened in a thread's stack), but this doesn't relate to the object's data.

    Also here's the issue with reentrancy. If the class you're using isn't reentrant (like QPixmap) you can't safely create and use its instances from different threads, even if the objects are separate.

    Last but not least, I guess with the DirectConnection the call is blocking and I will get the result back immediately, rather than the slot having to send the result of the slot processing back.

    It is not blocking, because it's not queued. It's a direct call, so there's nothing to block. A Qt::BlockingQueuedConnection is blocking because you return the control flow to the event loop and then the event loop blocks until the slot is executed. With Qt::DirectConnection you never return the control to the event loop, thus there's nothing to block.

    Kind regards.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.