Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problems with signals and slots in separate threads
QtWS25 Last Chance

Problems with signals and slots in separate threads

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 2.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    Henduww
    wrote on last edited by
    #1

    So I'm trying to make a fairly simple signal/slot setup with a thread sending the signal, and my main application picking up on it with a slot.
    I've been adviced not to subclass QThread, so I'm using a QThread object running an object of my own class.

    The abstract idea here is that I have a class "A" (main application), that has a slot "slot_a". My other class "B", has a signal "signal_b".
    In As constructor, a thread member is initialized, and an object of type B is moved into said thread. I then proceed to connect signal_b to slot_a. (Thread emits signal, main application receives it)
    This is where the problem occurs: The signal is indeed emitted, but the slot is never reached, unless I use Qt::DirectConnection, which I can't use, because the slot is supposed to update a couple of UI elements.

    Relevant code:
    A's constructor

    A::A(QWidget *parent)
    	: QMainWindow(parent), b_member(new B()), controllerThread(this)
    {
    	ui.setupUi(this);
    
    	b_member->moveToThread(&controllerThread);
    	QObject::connect(&controllerThread, &QThread::started, b_member, &B::slot_b); //this works just fine, "slot_b" is executed
    	QObject::connect(connectionHandler, &B::signal_b, this, &A::slot_a); // here, it only works with Qt:DirectConnection, which I DON'T want
            controllerThread->start(QThread::Priority::HighestPriority);
    }
    

    slot_a:

    void A::slot_a(const MyEnum check)
    {
            // this code is never reached. Breakpoint confirms that
    	if (check == MyEnum::SOMECHECK)
    	{
    		ui.label_someLabel->setVisible(false);
    	}
    	else if (check == MyEnum::SOMEOTHERCHECK)
    	{
    		ui.label_someLabel->setVisible(true);
    	}
    }
    // I need a QueuedConnection for this to work, apparently. Evidently does not work with DirectConnection at least. Causes runtime exception.
    

    signal_b: (defined in b.h)

    void signal_b(const MyEnum);
    

    signal_b is emitted from slot_b as such:

    void B::slot_b()
    {
        // this code is reached and executed
        emit signal_b(MyEnum::SOMECHECK);
    }
    

    Not sure if it's even relevant, or just a property of Qt and VS, but following the emition of singal_b just leads me to "qobject.cpp not found".

    I've spent far too many hours looking into this problem, and according to multiple other forum posts and stack overflow topics, I've done everything right.
    If anything's unclear, I'd be glad to clear it up. Thanks in advance!

    aha_1980A 1 Reply Last reply
    0
    • H Henduww

      So I'm trying to make a fairly simple signal/slot setup with a thread sending the signal, and my main application picking up on it with a slot.
      I've been adviced not to subclass QThread, so I'm using a QThread object running an object of my own class.

      The abstract idea here is that I have a class "A" (main application), that has a slot "slot_a". My other class "B", has a signal "signal_b".
      In As constructor, a thread member is initialized, and an object of type B is moved into said thread. I then proceed to connect signal_b to slot_a. (Thread emits signal, main application receives it)
      This is where the problem occurs: The signal is indeed emitted, but the slot is never reached, unless I use Qt::DirectConnection, which I can't use, because the slot is supposed to update a couple of UI elements.

      Relevant code:
      A's constructor

      A::A(QWidget *parent)
      	: QMainWindow(parent), b_member(new B()), controllerThread(this)
      {
      	ui.setupUi(this);
      
      	b_member->moveToThread(&controllerThread);
      	QObject::connect(&controllerThread, &QThread::started, b_member, &B::slot_b); //this works just fine, "slot_b" is executed
      	QObject::connect(connectionHandler, &B::signal_b, this, &A::slot_a); // here, it only works with Qt:DirectConnection, which I DON'T want
              controllerThread->start(QThread::Priority::HighestPriority);
      }
      

      slot_a:

      void A::slot_a(const MyEnum check)
      {
              // this code is never reached. Breakpoint confirms that
      	if (check == MyEnum::SOMECHECK)
      	{
      		ui.label_someLabel->setVisible(false);
      	}
      	else if (check == MyEnum::SOMEOTHERCHECK)
      	{
      		ui.label_someLabel->setVisible(true);
      	}
      }
      // I need a QueuedConnection for this to work, apparently. Evidently does not work with DirectConnection at least. Causes runtime exception.
      

      signal_b: (defined in b.h)

      void signal_b(const MyEnum);
      

      signal_b is emitted from slot_b as such:

      void B::slot_b()
      {
          // this code is reached and executed
          emit signal_b(MyEnum::SOMECHECK);
      }
      

      Not sure if it's even relevant, or just a property of Qt and VS, but following the emition of singal_b just leads me to "qobject.cpp not found".

      I've spent far too many hours looking into this problem, and according to multiple other forum posts and stack overflow topics, I've done everything right.
      If anything's unclear, I'd be glad to clear it up. Thanks in advance!

      aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi @Henduww,

      the connection types are described here.

      Qt::DirectConnection 1 The slot is invoked immediately when the signal is emitted. The slot is executed in the signalling thread.

      This means, a function call takes place, therefore your breakpoint is hit and the runtime problems occur.

      Qt::QueuedConnection 2 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.

      Here the function call is put in a mailbox of the receiver and is executed when the event loop has time for it.

      That leads me to the question: do you have an event loop running in the receiver thread?

      but following the emition of singal_b just leads me to "qobject.cpp not found".

      What do you mean by that?

      Regards

      Qt has to stay free or it will die.

      1 Reply Last reply
      3
      • H Offline
        H Offline
        Henduww
        wrote on last edited by
        #3

        Thanks for clearing those things up @aha_1980!
        I'm not sure how to implement an event loop, didn't realize I had to do that, but I'll look into it :)
        By the qobject.cpp not found I mean after following the emitting with breakpoints, I follow it into the moc file of my header, then I get led to "qobject.cpp" not found in Visual Studio. I don't think it's an error though, probably just VS that doesn't know how to step through the emition.

        1 Reply Last reply
        1
        • BjornWB Offline
          BjornWB Offline
          BjornW
          wrote on last edited by BjornW
          #4

          You should already have two event loops running, no need to create one yourself. When you do:

          controllerThread->start(QThread::Priority::HighestPriority);
          

          you start the controller thread event loop.

          I assume your widget "A" is running in the main thread (it has to?). When you do the typical

          return app.exec() 
          

          in main function you start the event loop on the main thread.

          You should now have two event loops running. What you need to look out for is what kind of arguments you are passing around in the signals/slots. In direct connections you can pass anything. If you want to pass anything over a queued connection you need to register the types with the qt meta system (most basic types such as ints etc are already registered). What are you sending? You shoul get a warning in your console if you try to pass anything that is unregistered.

          1 Reply Last reply
          5
          • BjornWB Offline
            BjornWB Offline
            BjornW
            wrote on last edited by
            #5

            Did you work it out?

            H 1 Reply Last reply
            0
            • BjornWB BjornW

              Did you work it out?

              H Offline
              H Offline
              Henduww
              wrote on last edited by
              #6

              @BjornW Thank you so much for clearing that up with the meta-types, that was indeed the problem!
              I've been on vacation the past week, so sorry for the delayed answer.
              The type I was passing was an enum class, which really wasn't necessary. I just changed it to a regular enum and made the signal/slots use int to make use of enums' implicit casting, works like a charm!

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved