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. Cross Thread Signals not working

Cross Thread Signals not working

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 3 Posters 514 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.
  • M Offline
    M Offline
    MaximBozek
    wrote on last edited by
    #1

    Hi,

    I made this class (CanHandler) to take CAN frames and translate them using a DBC file. I then used another class (ThreadHandler) to make this class run in a seperate thread (CanThread) AND connected my emitting signals to functions running on the main thread. I could then, using QProperty, show these values on my qml App. This all worked.

    Then I split up my CanHandler Class into 3 seperate classes and in the ThreadHandler class moved those to the CanThread. Now for some reason, the values aren't showing up on my qml app anymore. The "set_" function don't get called for some reason even though i connected them AND am emitting to the signals from the CanData class.

    This code was the exact same for my first situation, but now 3 classes get put in the canThread instead of 1.

    #ifndef THREADHANDLER_H
    #define THREADHANDLER_H
    
    #include <QObject>
    #include <QThread>
    #include "canraw.h"
    #include "cantranslation.h"
    #include "candata.h"
    
    class ThreadHandler : public QObject {
        Q_OBJECT
        Q_PROPERTY(double AccPedalPosition READ AccPedalPosition NOTIFY AccPedalPositionChanged)
        Q_PROPERTY(double BatteryLevel READ BatteryLevel NOTIFY BatteryLevelChanged)
        Q_PROPERTY(double EnginePercentLoadCurrentSpeed READ EnginePercentLoadCurrentSpeed NOTIFY EnginePercentLoadCurrentSpeedChanged)
        Q_PROPERTY(double EnginetorquePercentage READ EnginetorquePercentage NOTIFY EnginetorquePercentageChanged)
        Q_PROPERTY(double EngineSpeed READ EngineSpeed NOTIFY EngineSpeedChanged)
    public:
        explicit ThreadHandler(QObject *parent = nullptr) : QObject(parent) {
            canRaw->moveToThread(canThread);
            canTranslation->moveToThread(canThread);
            canData->moveToThread(canThread);
    
            connect(canThread, &QThread::started, canRaw, &CanRaw::init);
            connect(canThread, &QThread::started, canTranslation, &CanTranslation::init);
            connect(canThread, &QThread::started, canData, &CanData::init);
    
            connect(canData, &CanData::AccPedalPositionChanged, this, &ThreadHandler::set_AccPedalPosition);
            connect(canData, &CanData::BatteryLevelChanged, this, &ThreadHandler::set_BatteryLevel);
            connect(canData, &CanData::EnginePercentLoadCurrentSpeedChanged, this, &ThreadHandler::set_EnginePercentLoadCurrentSpeed);
            connect(canData, &CanData::EnginetorquePercentageChanged, this, &ThreadHandler::set_EnginetorquePercentage);
            connect(canData, &CanData::EngineSpeedChanged, this, &ThreadHandler::set_EngineSpeed);
    
            connect(canThread, &QThread::started, this, &ThreadHandler::canThreadFunction);
    
            canThread->start();
    
            qDebug() << "CanThread running in thread:" << QThread::currentThread();
        }
    
        ~ThreadHandler() {
            canThread->quit();
            canThread->wait();
        }
    
        double AccPedalPosition() const { return raw_AccpedalPosition; }
        double BatteryLevel() const { return raw_BatteryLevel; }
        double EnginePercentLoadCurrentSpeed() const { return raw_EnginePercentLoadCurrentSpeed; }
        double EnginetorquePercentage() const { return raw_EnginetorquePercentage; }
        double EngineSpeed() const { return raw_EngineSpeed; }
    
    public slots:
        void set_AccPedalPosition(double value) {
            qDebug() << "YES";
            if (raw_AccpedalPosition != value) {
                qDebug() << "YES";
                raw_AccpedalPosition = value;
                emit AccPedalPositionChanged(value);
            }
        }
        void set_BatteryLevel(double value) {
            qDebug() << "YES";
            if (raw_BatteryLevel != value) {
                qDebug() << "YES";
                raw_BatteryLevel = value;
                emit BatteryLevelChanged(value);
            }
        }
        void set_EnginePercentLoadCurrentSpeed(double value) {
            qDebug() << "YES";
            if (raw_EnginePercentLoadCurrentSpeed != value) {
                qDebug() << "YES";
                raw_EnginePercentLoadCurrentSpeed = value;
                emit EnginePercentLoadCurrentSpeedChanged(value);
            }
        }
        void set_EnginetorquePercentage(double value) {
            qDebug() << "YES";
            if (raw_EnginetorquePercentage != value) {
                qDebug() << "YES";
                raw_EnginetorquePercentage = value;
                emit EnginetorquePercentageChanged(value);
            }
        }
        void set_EngineSpeed(double value) {
            qDebug() << "YES";
            if (raw_EngineSpeed != value) {
                qDebug() << "YES";
                raw_EngineSpeed = value;
                emit EngineSpeedChanged(value);
            }
        }
    
    private:
        QThread *canThread = new QThread();
        CanRaw *canRaw = new CanRaw();
        CanTranslation *canTranslation = new CanTranslation();
        CanData *canData = new CanData();
    
        double raw_AccpedalPosition = 0.0;
        double raw_BatteryLevel = 0.0;
        double raw_EnginePercentLoadCurrentSpeed = 0.0;
        double raw_EnginetorquePercentage = 0.0;
        double raw_EngineSpeed = 0.0;
    
    signals:
        void AccPedalPositionChanged(double value);
        void BatteryLevelChanged(double value);
        void EnginePercentLoadCurrentSpeedChanged(double value);
        void EnginetorquePercentageChanged(double value);
        void EngineSpeedChanged(double value);
    };
    
    #endif // THREADHANDLER_H
    
    

    What could be the issue here?

    Christian EhrlicherC 1 Reply Last reply
    0
    • M MaximBozek

      Hi,

      I made this class (CanHandler) to take CAN frames and translate them using a DBC file. I then used another class (ThreadHandler) to make this class run in a seperate thread (CanThread) AND connected my emitting signals to functions running on the main thread. I could then, using QProperty, show these values on my qml App. This all worked.

      Then I split up my CanHandler Class into 3 seperate classes and in the ThreadHandler class moved those to the CanThread. Now for some reason, the values aren't showing up on my qml app anymore. The "set_" function don't get called for some reason even though i connected them AND am emitting to the signals from the CanData class.

      This code was the exact same for my first situation, but now 3 classes get put in the canThread instead of 1.

      #ifndef THREADHANDLER_H
      #define THREADHANDLER_H
      
      #include <QObject>
      #include <QThread>
      #include "canraw.h"
      #include "cantranslation.h"
      #include "candata.h"
      
      class ThreadHandler : public QObject {
          Q_OBJECT
          Q_PROPERTY(double AccPedalPosition READ AccPedalPosition NOTIFY AccPedalPositionChanged)
          Q_PROPERTY(double BatteryLevel READ BatteryLevel NOTIFY BatteryLevelChanged)
          Q_PROPERTY(double EnginePercentLoadCurrentSpeed READ EnginePercentLoadCurrentSpeed NOTIFY EnginePercentLoadCurrentSpeedChanged)
          Q_PROPERTY(double EnginetorquePercentage READ EnginetorquePercentage NOTIFY EnginetorquePercentageChanged)
          Q_PROPERTY(double EngineSpeed READ EngineSpeed NOTIFY EngineSpeedChanged)
      public:
          explicit ThreadHandler(QObject *parent = nullptr) : QObject(parent) {
              canRaw->moveToThread(canThread);
              canTranslation->moveToThread(canThread);
              canData->moveToThread(canThread);
      
              connect(canThread, &QThread::started, canRaw, &CanRaw::init);
              connect(canThread, &QThread::started, canTranslation, &CanTranslation::init);
              connect(canThread, &QThread::started, canData, &CanData::init);
      
              connect(canData, &CanData::AccPedalPositionChanged, this, &ThreadHandler::set_AccPedalPosition);
              connect(canData, &CanData::BatteryLevelChanged, this, &ThreadHandler::set_BatteryLevel);
              connect(canData, &CanData::EnginePercentLoadCurrentSpeedChanged, this, &ThreadHandler::set_EnginePercentLoadCurrentSpeed);
              connect(canData, &CanData::EnginetorquePercentageChanged, this, &ThreadHandler::set_EnginetorquePercentage);
              connect(canData, &CanData::EngineSpeedChanged, this, &ThreadHandler::set_EngineSpeed);
      
              connect(canThread, &QThread::started, this, &ThreadHandler::canThreadFunction);
      
              canThread->start();
      
              qDebug() << "CanThread running in thread:" << QThread::currentThread();
          }
      
          ~ThreadHandler() {
              canThread->quit();
              canThread->wait();
          }
      
          double AccPedalPosition() const { return raw_AccpedalPosition; }
          double BatteryLevel() const { return raw_BatteryLevel; }
          double EnginePercentLoadCurrentSpeed() const { return raw_EnginePercentLoadCurrentSpeed; }
          double EnginetorquePercentage() const { return raw_EnginetorquePercentage; }
          double EngineSpeed() const { return raw_EngineSpeed; }
      
      public slots:
          void set_AccPedalPosition(double value) {
              qDebug() << "YES";
              if (raw_AccpedalPosition != value) {
                  qDebug() << "YES";
                  raw_AccpedalPosition = value;
                  emit AccPedalPositionChanged(value);
              }
          }
          void set_BatteryLevel(double value) {
              qDebug() << "YES";
              if (raw_BatteryLevel != value) {
                  qDebug() << "YES";
                  raw_BatteryLevel = value;
                  emit BatteryLevelChanged(value);
              }
          }
          void set_EnginePercentLoadCurrentSpeed(double value) {
              qDebug() << "YES";
              if (raw_EnginePercentLoadCurrentSpeed != value) {
                  qDebug() << "YES";
                  raw_EnginePercentLoadCurrentSpeed = value;
                  emit EnginePercentLoadCurrentSpeedChanged(value);
              }
          }
          void set_EnginetorquePercentage(double value) {
              qDebug() << "YES";
              if (raw_EnginetorquePercentage != value) {
                  qDebug() << "YES";
                  raw_EnginetorquePercentage = value;
                  emit EnginetorquePercentageChanged(value);
              }
          }
          void set_EngineSpeed(double value) {
              qDebug() << "YES";
              if (raw_EngineSpeed != value) {
                  qDebug() << "YES";
                  raw_EngineSpeed = value;
                  emit EngineSpeedChanged(value);
              }
          }
      
      private:
          QThread *canThread = new QThread();
          CanRaw *canRaw = new CanRaw();
          CanTranslation *canTranslation = new CanTranslation();
          CanData *canData = new CanData();
      
          double raw_AccpedalPosition = 0.0;
          double raw_BatteryLevel = 0.0;
          double raw_EnginePercentLoadCurrentSpeed = 0.0;
          double raw_EnginetorquePercentage = 0.0;
          double raw_EngineSpeed = 0.0;
      
      signals:
          void AccPedalPositionChanged(double value);
          void BatteryLevelChanged(double value);
          void EnginePercentLoadCurrentSpeedChanged(double value);
          void EnginetorquePercentageChanged(double value);
          void EngineSpeedChanged(double value);
      };
      
      #endif // THREADHANDLER_H
      
      

      What could be the issue here?

      Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @MaximBozek said in Cross Thread Signals not working:

      connect(canThread, &QThread::started, this, &ThreadHandler::canThreadFunction);

      Your example does not even compile.
      Please provide a minimal, compilable example or at least all relevant code pieces. Are you sure your init functions all work correct?

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      M 2 Replies Last reply
      3
      • Christian EhrlicherC Christian Ehrlicher

        @MaximBozek said in Cross Thread Signals not working:

        connect(canThread, &QThread::started, this, &ThreadHandler::canThreadFunction);

        Your example does not even compile.
        Please provide a minimal, compilable example or at least all relevant code pieces. Are you sure your init functions all work correct?

        M Offline
        M Offline
        MaximBozek
        wrote on last edited by
        #3

        @Christian-Ehrlicher My bad, this line should not be in the program, I can't get you the full project till monday

        1 Reply Last reply
        0
        • Christian EhrlicherC Christian Ehrlicher

          @MaximBozek said in Cross Thread Signals not working:

          connect(canThread, &QThread::started, this, &ThreadHandler::canThreadFunction);

          Your example does not even compile.
          Please provide a minimal, compilable example or at least all relevant code pieces. Are you sure your init functions all work correct?

          M Offline
          M Offline
          MaximBozek
          wrote on last edited by
          #4

          @Christian-Ehrlicher The init functions are working fine, but my main issue is that the signals form the CanData Class i am emitting, are not carrying out the functions from the ThreadHandler Class (those 5 connections i am making).

          Pl45m4P 1 Reply Last reply
          0
          • M MaximBozek

            @Christian-Ehrlicher The init functions are working fine, but my main issue is that the signals form the CanData Class i am emitting, are not carrying out the functions from the ThreadHandler Class (those 5 connections i am making).

            Pl45m4P Online
            Pl45m4P Online
            Pl45m4
            wrote on last edited by
            #5

            @MaximBozek

            What do your CAN classes look like?


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            M 1 Reply Last reply
            0
            • Pl45m4P Pl45m4

              @MaximBozek

              What do your CAN classes look like?

              M Offline
              M Offline
              MaximBozek
              wrote on last edited by
              #6

              @Pl45m4

              Tried sending the code in the text editor, got a spam warning. Tried sending a wetransfer link, got a spam warning> How should I send the code?

              Pl45m4P 1 Reply Last reply
              1
              • M MaximBozek

                @Pl45m4

                Tried sending the code in the text editor, got a spam warning. Tried sending a wetransfer link, got a spam warning> How should I send the code?

                Pl45m4P Online
                Pl45m4P Online
                Pl45m4
                wrote on last edited by Pl45m4
                #7

                @MaximBozek

                Try again using code tags here in the forum (the </> button)
                I upvoted your comment. With increasing reputation the spam restrictions become less harsh


                If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                ~E. W. Dijkstra

                M 1 Reply Last reply
                0
                • Pl45m4P Pl45m4

                  @MaximBozek

                  Try again using code tags here in the forum (the </> button)
                  I upvoted your comment. With increasing reputation the spam restrictions become less harsh

                  M Offline
                  M Offline
                  MaximBozek
                  wrote on last edited by
                  #8

                  Tried even my smallest class and it was warning spam, here is only the source code from that class, the one where i emit the signals:

                  #include "candata.h"
                  
                  CanData::CanData(QObject *parent) : QObject(parent) {}
                  void CanData::init() {
                      qDebug() << "CanData running in thread:" << QThread::currentThread();
                  }
                  void CanData::parseSignalValues(const QMap<QString, QVariant> &signalValues) {
                      for (auto it = signalValues.cbegin(); it != signalValues.cend(); ++it) {
                          QString signalName = it.key();
                          QVariant value = it.value();
                          qDebug() << signalName << ":" << value.toDouble();
                          if (signalName == "Acc_pedal_position1") {
                              emit AccPedalPositionChanged(value.toDouble());
                          } else if (signalName == "Battery_Level") {
                              emit BatteryLevelChanged(value.toDouble());
                          } else if (signalName == "Engine_Percent_Load_Current_Spd") {
                              emit EnginePercentLoadCurrentSpeedChanged(value.toDouble());
                          } else if (signalName == "Actual_Engine_porcentage_torque") {
                              emit EnginetorquePercentageChanged(value.toDouble());
                          } else if (signalName == "Engine_Speed") {
                              emit EngineSpeedChanged(value.toDouble());
                          }
                      }
                  }
                  
                  
                  Pl45m4P 1 Reply Last reply
                  0
                  • M MaximBozek

                    Tried even my smallest class and it was warning spam, here is only the source code from that class, the one where i emit the signals:

                    #include "candata.h"
                    
                    CanData::CanData(QObject *parent) : QObject(parent) {}
                    void CanData::init() {
                        qDebug() << "CanData running in thread:" << QThread::currentThread();
                    }
                    void CanData::parseSignalValues(const QMap<QString, QVariant> &signalValues) {
                        for (auto it = signalValues.cbegin(); it != signalValues.cend(); ++it) {
                            QString signalName = it.key();
                            QVariant value = it.value();
                            qDebug() << signalName << ":" << value.toDouble();
                            if (signalName == "Acc_pedal_position1") {
                                emit AccPedalPositionChanged(value.toDouble());
                            } else if (signalName == "Battery_Level") {
                                emit BatteryLevelChanged(value.toDouble());
                            } else if (signalName == "Engine_Percent_Load_Current_Spd") {
                                emit EnginePercentLoadCurrentSpeedChanged(value.toDouble());
                            } else if (signalName == "Actual_Engine_porcentage_torque") {
                                emit EnginetorquePercentageChanged(value.toDouble());
                            } else if (signalName == "Engine_Speed") {
                                emit EngineSpeedChanged(value.toDouble());
                            }
                        }
                    }
                    
                    
                    Pl45m4P Online
                    Pl45m4P Online
                    Pl45m4
                    wrote on last edited by Pl45m4
                    #9

                    @MaximBozek said in Cross Thread Signals not working:

                    void CanData::parseSignalValues
                    

                    Where / From where you call this function?

                    Also as @Christian-Ehrlicher said before, make sure everything is initialized correctly and you actually run your threaded workers (canRaw, canTranslation and canData)... because just moving them won't start them...
                    and, for example your CanData::init

                    void CanData::init() {
                        qDebug() << "CanData running in thread:" << QThread::currentThread();
                    }
                    

                    which is connected to QThread::started here:

                    connect(canThread, &QThread::started, canData, &CanData::init);
                    

                    does pretty much nothing :)


                    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                    ~E. W. Dijkstra

                    M 1 Reply Last reply
                    0
                    • Pl45m4P Pl45m4

                      @MaximBozek said in Cross Thread Signals not working:

                      void CanData::parseSignalValues
                      

                      Where / From where you call this function?

                      Also as @Christian-Ehrlicher said before, make sure everything is initialized correctly and you actually run your threaded workers (canRaw, canTranslation and canData)... because just moving them won't start them...
                      and, for example your CanData::init

                      void CanData::init() {
                          qDebug() << "CanData running in thread:" << QThread::currentThread();
                      }
                      

                      which is connected to QThread::started here:

                      connect(canThread, &QThread::started, canData, &CanData::init);
                      

                      does pretty much nothing :)

                      M Offline
                      M Offline
                      MaximBozek
                      wrote on last edited by
                      #10

                      @Pl45m4 How would you run my workers in this case?

                      Pl45m4P 1 Reply Last reply
                      0
                      • M MaximBozek

                        @Pl45m4 How would you run my workers in this case?

                        Pl45m4P Online
                        Pl45m4P Online
                        Pl45m4
                        wrote on last edited by
                        #11

                        @MaximBozek

                        How should we be able to tell? It's your program and we can just see a tiny snippet. That's why I asked... so you can check it yourself.
                        Who calls CanData::parseSignalValues?! From what we can see, it's called nowhere (or at least in a class that we can't see), that's why no signals are emitted.
                        Just moving the object to the new thread and starting the thread won't start the worker.

                        Go through your code and check your logic... from the creation of all the workers to moving them to a new thread and connecting your signals...


                        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                        ~E. W. Dijkstra

                        M 1 Reply Last reply
                        1
                        • Pl45m4P Pl45m4

                          @MaximBozek

                          How should we be able to tell? It's your program and we can just see a tiny snippet. That's why I asked... so you can check it yourself.
                          Who calls CanData::parseSignalValues?! From what we can see, it's called nowhere (or at least in a class that we can't see), that's why no signals are emitted.
                          Just moving the object to the new thread and starting the thread won't start the worker.

                          Go through your code and check your logic... from the creation of all the workers to moving them to a new thread and connecting your signals...

                          M Offline
                          M Offline
                          MaximBozek
                          wrote on last edited by
                          #12

                          @Pl45m4 I am calling CanData::parseSignalValues somewhere in my code, but I can't really show this... This forum doesn't really allow long posts to be posted, unless you have the necessary reputation (?). This is a rough explaination:

                          I while loop until the vcan0 CAN device is connected to the program. Then I translate every CAN frame that comes in (CanTranslation class). Then I send the parsed values (comes out of the translation as a QMap array) to CanData::parseSignalValues which splits up the QMap array and emits every values seperately. This emit should trigger a function inside the ThreadHandler class, but it is not.

                          Like i said in the initial post, this used to work, before I split up my initial class (CanHandler) in 3: CanRaw, CanTranslation and CanData.

                          Pl45m4P 1 Reply Last reply
                          0
                          • M MaximBozek

                            @Pl45m4 I am calling CanData::parseSignalValues somewhere in my code, but I can't really show this... This forum doesn't really allow long posts to be posted, unless you have the necessary reputation (?). This is a rough explaination:

                            I while loop until the vcan0 CAN device is connected to the program. Then I translate every CAN frame that comes in (CanTranslation class). Then I send the parsed values (comes out of the translation as a QMap array) to CanData::parseSignalValues which splits up the QMap array and emits every values seperately. This emit should trigger a function inside the ThreadHandler class, but it is not.

                            Like i said in the initial post, this used to work, before I split up my initial class (CanHandler) in 3: CanRaw, CanTranslation and CanData.

                            Pl45m4P Online
                            Pl45m4P Online
                            Pl45m4
                            wrote on last edited by
                            #13

                            @MaximBozek said in Cross Thread Signals not working:

                            CanData::parseSignalValues which splits up the QMap array and emits every values seperately

                            Does this work? Is this function actually called? This way you can check if it's a logical error in your code or some issue with the signal connection.

                            This forum doesn't really allow long posts to be posted, unless you have the necessary reputation (?)

                            Try something like pastebin if you don't mind sharing your code (at least more relevant bits) there.


                            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                            ~E. W. Dijkstra

                            M 1 Reply Last reply
                            0
                            • Pl45m4P Pl45m4

                              @MaximBozek said in Cross Thread Signals not working:

                              CanData::parseSignalValues which splits up the QMap array and emits every values seperately

                              Does this work? Is this function actually called? This way you can check if it's a logical error in your code or some issue with the signal connection.

                              This forum doesn't really allow long posts to be posted, unless you have the necessary reputation (?)

                              Try something like pastebin if you don't mind sharing your code (at least more relevant bits) there.

                              M Offline
                              M Offline
                              MaximBozek
                              wrote on last edited by
                              #14

                              @Pl45m4 I just tried the exact same code, but all function in one class. THIS WORKS

                              When I split up my class, CanData::parseSignalValues was being called (checked with a simple qDebug()).

                              CanData::parseSignalValues is posted in reply #8 by the way.

                              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