Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

connect doesn't call a slot but invokes lambda



  • Hi,

    Could someone enlighten me what I'm doing wrong that basic connect syntax:

    connect(myObj, &MyObjClass::signal1, this, &ThisClass::signal1Slot);
    

    doesn't work.

    (No matter ThisClass::signal1Slot() method is ordinary method or marked as slots)
    but

    connect(myObj, &MyObjClass::signal1, [=]{ signal1Slot(); });
    

    is invoked as intended

    but

    connect(myObj, &MyObjClass::signal1, this, [=]{ signal1Slot(); });
    

    doesn't.

    Also 'old syntax' with SIGNAL and SLOT keywords doesn't work.

    One thing could be a key here: signal1 is called from another thread (and not QThread subclass) than the receiver thread.



  • You'll have to provide a little more information. What do you mean by "doesn't work". It doesn't compile ? Does it compile but the slot is not being called ?
    Are there any debug messages being printed about the connect call ?
    Can you show the signatures of the signal and the slot ?



  • To clarify more:
    Signatures are as I wrote:

    connect(myObj, &MyObjClass::signal1, this, &ThisClass::signal1Slot); // doesn't work
    connect(myObj, &MyObjClass::signal1, [=]{ signal1Slot(); }); // only one that works
    connect(myObj, &MyObjClass::signal1, this, [=]{ signal1Slot(); }); // doesn't
    
    

    All options above compiles fine, any message about that connections either during compilation or runtime. Any troublesome message at all :-)

    With old syntax also there is no any runtime warning and of course in this case `slots' keyword is used above slot method declaration.


  • Lifetime Qt Champion

    Hi,

    Maybe a silly question but, how do you know it's not called ?
    Can you show the complete code that triggers this ?
    What version of Qt are you using ?
    On what platform ?
    What compiler ?



  • I'm on Arch Linux with Qt 5.13. My app is compilled with GCC 9.1.
    And simply I set debug message inside the slot method.

    This "other thread" signal is emitted from audio callback function. (RtAudio actually) and by debug message before emit signal1(); I can detect it is indeed invoked.

    In general all works as intended, but just for my knowledge I'm wondering why only that particular way of connection is respected.

    Shall I write even more?


  • Moderators

    @seelook said in connect doesn't call a slot but invokes lambda:

    connect(myObj, &MyObjClass::signal1, [=]{ signal1Slot(); });
    

    is invoked as intended

    This connection runs the lambda in myObj's thread.

    All your other connections try to run the lambda/slot in this's thread.

    One thing could be a key here: signal1 is called from another thread (and not QThread subclass) than the receiver thread.

    Does this live in a thread that has a running, non-blocked event loop?



  • I forgot to explain one thing, but I forgot it for myself as well:
    Year ago I moved this to its own thread (audio data preparing heavy load), but I just forgot. Sorry.
    But this explains everything.

    connect(myObj, &MyObjClass::signal1, [=]{ signal1Slot(); });
    

    This connection runs the lambda in myObj's thread.

    This is so obvious that I even didn't think about it. It expalins how it works.
    @JKSH Thank You a lot!
    But this is first conclusion.
    Another one is:

                   main thread (event loop)
                            ^        \
                           /          \
                          /            \         
             thread_A(sender)      thread_B(receiver)
    

    Signal sent by sender in thread A has to pass trough main thread to be delivered to receiver in thread B, in other words somewhere in main thread has to be receiver of thread A signal which will invoke slot in thread B (or will forward signal to it). Makes sense.
    So I have to manage that.


  • Moderators

    @seelook said in connect doesn't call a slot but invokes lambda:

                   main thread (event loop)
                            ^        \
                           /          \
                          /            \         
             thread_A(sender)      thread_B(receiver)
    

    Signal sent by sender in thread A has to pass trough main thread to be delivered to receiver in thread B, in other words somewhere in main thread has to be receiver of thread A signal which will invoke slot in thread B (or will forward signal to it).

    In your diagram, Thread B must still have a running event loop. If it doesn't have an event loop, then Thread B can't receive any signals and can't have any slot invoked.

    A signal can go straight from Thread A to Thread B without going through the main thread. Thread B just needs a running event loop.


Log in to reply