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. Optimal way to establish large number of QTimers
Forum Updated to NodeBB v4.3 + New Features

Optimal way to establish large number of QTimers

Scheduled Pinned Locked Moved Unsolved General and Desktop
33 Posts 6 Posters 10.1k Views 4 Watching
  • 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.
  • J Offline
    J Offline
    jars121
    wrote on last edited by
    #10

    Brilliant, thanks again!

    The QObject methodology certainly makes sense, so I'll give that a go to start with. I'm going to start off with 3 threads for the time being, and look to consolidate if need be.

    I'll go through your linked example over the coming day or so, and report back with progress.

    1 Reply Last reply
    0
    • J Offline
      J Offline
      jars121
      wrote on last edited by
      #11

      I've been giving this some further thought (haven't had a chance to implement the approach listed above as of yet), and was hoping to get some feedback.

      The current approach, as per my original question/post, is to create a separate QTimer for each of the 64 inputs. What I've been thinking about, is rather having a single QTimer, the resultant timeout function for which then runs through each of the individual inputs' functions. For example, if I set the single QTimer to a timeout of 1/1000 seconds (1000Hz), each input function will be able to run at 1000Hz. If the specified poll frequency of a given input is only 500Hz, the main QTimer timeout function simply skips the call to the individual input function every second time the timeout is called.

      Does that make sense? The process seems to be simpler, as you're dealing with a single QTimer rather than 64, but the actual overhead of using 64 individual QTimers might be entirely insignificant, I really don't know. I'm happy to progress down the path of 64 individual QTimers and threads, but wanted to pose this question before doing so.

      jsulmJ JKSHJ 2 Replies Last reply
      0
      • J jars121

        I've been giving this some further thought (haven't had a chance to implement the approach listed above as of yet), and was hoping to get some feedback.

        The current approach, as per my original question/post, is to create a separate QTimer for each of the 64 inputs. What I've been thinking about, is rather having a single QTimer, the resultant timeout function for which then runs through each of the individual inputs' functions. For example, if I set the single QTimer to a timeout of 1/1000 seconds (1000Hz), each input function will be able to run at 1000Hz. If the specified poll frequency of a given input is only 500Hz, the main QTimer timeout function simply skips the call to the individual input function every second time the timeout is called.

        Does that make sense? The process seems to be simpler, as you're dealing with a single QTimer rather than 64, but the actual overhead of using 64 individual QTimers might be entirely insignificant, I really don't know. I'm happy to progress down the path of 64 individual QTimers and threads, but wanted to pose this question before doing so.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #12

        @jars121 I would not use 64 timers. In my opinion it's simply waste of resources. Your second approach is far better.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • J Offline
          J Offline
          jars121
          wrote on last edited by
          #13

          Thanks @jsulm much appreciated! I've used the second approach before and it worked quite well, so I'm happy to build this functionality for testing purposes.

          1 Reply Last reply
          0
          • J jars121

            I've been giving this some further thought (haven't had a chance to implement the approach listed above as of yet), and was hoping to get some feedback.

            The current approach, as per my original question/post, is to create a separate QTimer for each of the 64 inputs. What I've been thinking about, is rather having a single QTimer, the resultant timeout function for which then runs through each of the individual inputs' functions. For example, if I set the single QTimer to a timeout of 1/1000 seconds (1000Hz), each input function will be able to run at 1000Hz. If the specified poll frequency of a given input is only 500Hz, the main QTimer timeout function simply skips the call to the individual input function every second time the timeout is called.

            Does that make sense? The process seems to be simpler, as you're dealing with a single QTimer rather than 64, but the actual overhead of using 64 individual QTimers might be entirely insignificant, I really don't know. I'm happy to progress down the path of 64 individual QTimers and threads, but wanted to pose this question before doing so.

            JKSHJ Offline
            JKSHJ Offline
            JKSH
            Moderators
            wrote on last edited by JKSH
            #14

            @jars121 said in Optimal way to establish large number of QTimers:

            The current approach, as per my original question/post, is to create a separate QTimer for each of the 64 inputs. What I've been thinking about, is rather having a single QTimer, the resultant timeout function for which then runs through each of the individual inputs' functions.

            Having 1 timer will give you a lot less jitter than having 64 timers. If you know exactly how frequently you want each function to run, and if there is one "common denominator" between all the times (e.g. all timers are multiples of 10 ms), then consider using just one timer. There's one downside: It will be more tedious to add another timed function if the new loop period is not an integer multiple of your existing timer's period.

            Before you continue though, there are two important details to know:

            1. What is your operating system?
            2. How much timing error can your app tolerate?

            I ask this because for an OS that's not real-time (especially Windows), you are unlikely to be able to fire events at precisely 1 ms intervals.

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            1 Reply Last reply
            5
            • J Offline
              J Offline
              jars121
              wrote on last edited by
              #15

              Very valid points, thank you @JKSH

              The OS will be Embedded Linux. I'm well aware that it's not a RTOS, so will work within the confines of a non-RTOS. I may well end up only being able to accurately use 2ms (500Hz), or less, but I want to establish/develop the most optimal approach to begin with, and then start testing the possible frequencies.

              In terms of the timed functions and their reference to the 1ms QTimer, that's something I'll need to work around as well.

              kshegunovK 1 Reply Last reply
              0
              • J jars121

                Very valid points, thank you @JKSH

                The OS will be Embedded Linux. I'm well aware that it's not a RTOS, so will work within the confines of a non-RTOS. I may well end up only being able to accurately use 2ms (500Hz), or less, but I want to establish/develop the most optimal approach to begin with, and then start testing the possible frequencies.

                In terms of the timed functions and their reference to the 1ms QTimer, that's something I'll need to work around as well.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #16

                @jars121 said in Optimal way to establish large number of QTimers:

                I may well end up only being able to accurately use 2ms (500Hz), or less, but I want to establish/develop the most optimal approach to begin with, and then start testing the possible frequencies.

                I think @JKSH's point is that you really shouldn't expect jitters under about 10ms unless your system supports precise timers, which may or may not be the case. In any case, for polling, which you shouldn't use for time critical data anyway, that's more than enough. In principle I'd always opt for a single timer (i.e. a single file descriptor) that will give the "tics" and then in the timeout handler check whatever timeouts have expired to fire whatever events I want. You can, if needed, run an infinite event loop (do it in a separate thread) that will generate timeout events as fast as the system can process them by setting the timeout for the timer to 0, i.e. timer->start(0), but this would eat up all the CPU time for the core the thread runs on so it might or might not be appropriate for your case. Consider the following example code (untested) for the single timer approach, you'd need to wrap it in a nice class though:

                QTimer timer;                                 //< Master poll timer
                QVector<qint32> timeouts(...); //< Poll timeouts
                QVector<qint64> activated(timeouts.size(), QDateTime::currentMSecsSinceEpoch());    //< When was the last activation
                
                timer.start(100); 
                
                QObject::connect(&timer, &QTimer::timeout, &timer, [&timeouts, &activated] () -> void {
                    // Check each of the timeouts for expiration
                    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
                    for (qint32 i = 0, size = timeouts.size(); i < size; i++)  {
                         if ((currentTime - activated[i]) / timeouts[i])  {
                             activated[i] = currentTime;
                             // ... We need to fire the handler for the i-th polling operation here
                         }
                    }
                });
                

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                5
                • J Offline
                  J Offline
                  jars121
                  wrote on last edited by
                  #17

                  Thank you @kshegunov that's very much in line with how I had planned on catering for inputs with varying poll frequencies :)

                  I've only just had time to get around to addressing this in my application, and I'm having some trouble with threads. Here's what I've got so far, which is working, but the timeout functions are running on the main thread rather than on separate threads. I understand why this is the case, but haven't been able to get the separate threads working (I've included a SIGNAL/SLOT connect below which I believe is the right way to approach it, but I'd appreciate some points/feedback).

                  
                      //main.cpp
                  
                      qDebug() << "Main thread ID: "" << QThread::currentThread();
                  
                      QThread* analogThread = new QThread(this);
                      QTimer* analogTimer = new QTimer();
                      analogTimer->setInterval(1);
                      connect(analogTimer, &QTimer::timeout, this, &Main::analogTimeout);
                      analogTimer->start();
                      analogTimer->moveToThread(analogThread);
                  
                      QThread* digitalThread = new QThread(this);
                      QTimer* digitalTimer = new QTimer();
                      digitalTimer->setInterval(1);
                      connect(digitalTimer, &QTimer::timeout, this, &Main::digitalTimeout);
                      digitalTimer->start();
                      digitalTimer->moveToThread(digitalThread);
                  
                      //The below commented lines represent how I believe the timers should be started within the thread
                      //I would then remove the timer->start() calls above.
                      //connect(analogThread, SIGNAL(analogStarted()), analogTimer, SLOT(analogTimeout()));
                      analogThread->start();
                  
                      //connect(digitalThread, SIGNAL(digitalStarted()), digitalTimer, SLOT(digitalTimeout()));
                      digitalThread->start();
                  }
                  
                  void Main::analogTimeout()
                  {
                      qDebug() << "Analog: " << QThread::currentThread();
                  }
                  
                  void Main::digitalTimeout()
                  {
                      qDebug() << "Digital: " << QThread::currentThread();
                  }
                  

                  As you would expect, the result at the moment is that the "Main thread", "analogTimeout" and "digitalTimeout" qDebug()'s all show execution within the same thread. I'm missing a key understanding here; how do I move the analogTimer and digitalTimer into analogThread and digitalThread respectively?

                  Thanks!

                  kshegunovK 1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    ambershark
                    wrote on last edited by ambershark
                    #18

                    So you normally would call moveToThread before connecting your signals. However in your case that won't work. You are trying to move only a timer to a thread. What you want is moving a QObject based class to a thread. Then all the signals it handles will be on that thread.

                    So in your case you would need some class that has your slots you want to handle the timer:

                    class TimerHandler : public QObject
                    {
                       Q_OBJECT
                    public:
                        TimerHandler(QObject *parent = nullptr) : QObject(parent) { }
                    
                    public slots:
                        void timerTicked() { qDebug() << "ticked in thread " << QThread::currentThreadId(); }
                    };
                    
                    // ...
                    
                    QThread *analogThread = new QThread();
                    TimerHandler *analogTimerHandler = new TimerHandler();
                    analogTimerHandler->moveToThread(analogThread);
                    QTimer *analogTimer = new QTimer();
                    analogTimer->setInterval(1); // this is a bad idea :)
                    connect(analogTimer, SIGNAL(timeout()), analogTimerHandler, SLOT(timerTicked()));
                    analogThread->start();
                    analogTimer->start();
                    
                    

                    Something like that should work. That code may not be 100% accurate since I just typed it from my head with no auto completion or a compile test, but look up syntax if I missed some and it should work. The idea is what you needed.

                    Also having a timer that tries to fire every 1ms is going to probably give you 100% cpu usage on the processor that thread is on. Not a great design. You're better off in a for loop in your thread that just sleeps for an interval you need (1ms?). However even a for loop with 1ms sleep while it will be less intense than a signal it will still more than likely cause 100% cpu usage on that cpu.

                    My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                    1 Reply Last reply
                    2
                    • J jars121

                      Thank you @kshegunov that's very much in line with how I had planned on catering for inputs with varying poll frequencies :)

                      I've only just had time to get around to addressing this in my application, and I'm having some trouble with threads. Here's what I've got so far, which is working, but the timeout functions are running on the main thread rather than on separate threads. I understand why this is the case, but haven't been able to get the separate threads working (I've included a SIGNAL/SLOT connect below which I believe is the right way to approach it, but I'd appreciate some points/feedback).

                      
                          //main.cpp
                      
                          qDebug() << "Main thread ID: "" << QThread::currentThread();
                      
                          QThread* analogThread = new QThread(this);
                          QTimer* analogTimer = new QTimer();
                          analogTimer->setInterval(1);
                          connect(analogTimer, &QTimer::timeout, this, &Main::analogTimeout);
                          analogTimer->start();
                          analogTimer->moveToThread(analogThread);
                      
                          QThread* digitalThread = new QThread(this);
                          QTimer* digitalTimer = new QTimer();
                          digitalTimer->setInterval(1);
                          connect(digitalTimer, &QTimer::timeout, this, &Main::digitalTimeout);
                          digitalTimer->start();
                          digitalTimer->moveToThread(digitalThread);
                      
                          //The below commented lines represent how I believe the timers should be started within the thread
                          //I would then remove the timer->start() calls above.
                          //connect(analogThread, SIGNAL(analogStarted()), analogTimer, SLOT(analogTimeout()));
                          analogThread->start();
                      
                          //connect(digitalThread, SIGNAL(digitalStarted()), digitalTimer, SLOT(digitalTimeout()));
                          digitalThread->start();
                      }
                      
                      void Main::analogTimeout()
                      {
                          qDebug() << "Analog: " << QThread::currentThread();
                      }
                      
                      void Main::digitalTimeout()
                      {
                          qDebug() << "Digital: " << QThread::currentThread();
                      }
                      

                      As you would expect, the result at the moment is that the "Main thread", "analogTimeout" and "digitalTimeout" qDebug()'s all show execution within the same thread. I'm missing a key understanding here; how do I move the analogTimer and digitalTimer into analogThread and digitalThread respectively?

                      Thanks!

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by kshegunov
                      #19

                      In addition to what @ambershark wrote, you should read this. The thread the object is assigned to is relevant to its slots, not so much to the signals it emits.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      2
                      • J Offline
                        J Offline
                        jars121
                        wrote on last edited by
                        #20

                        Thank you both, much appreciated as always. The 1ms aspect isn't a hard requirement, more a 'best case' if the CPU is able to support it. I now understand your approach, regarding moving of the QObject to the thread rather than the QTimer itself.

                        Having said that, I'm more inclined to put the acquisition functions in a loop on its thread as you mentioned. I'll take a timestamp at the start of each iteration of the loop, and then sleep for a calculated period of time at the end of the loop, based on the current time, the beginning time and the desired poll frequency. E.g.:

                        while (1)
                        {
                            timeStamp = currentTime();
                            //do stuff
                        
                            sleep((1/pollFrequency)-(currentTime() - timeStamp));
                        }
                        

                        I'll give this approach a go and play with frequencies to see what the CPU can handle.

                        JKSHJ kshegunovK 2 Replies Last reply
                        0
                        • J jars121

                          Thank you both, much appreciated as always. The 1ms aspect isn't a hard requirement, more a 'best case' if the CPU is able to support it. I now understand your approach, regarding moving of the QObject to the thread rather than the QTimer itself.

                          Having said that, I'm more inclined to put the acquisition functions in a loop on its thread as you mentioned. I'll take a timestamp at the start of each iteration of the loop, and then sleep for a calculated period of time at the end of the loop, based on the current time, the beginning time and the desired poll frequency. E.g.:

                          while (1)
                          {
                              timeStamp = currentTime();
                              //do stuff
                          
                              sleep((1/pollFrequency)-(currentTime() - timeStamp));
                          }
                          

                          I'll give this approach a go and play with frequencies to see what the CPU can handle.

                          JKSHJ Offline
                          JKSHJ Offline
                          JKSH
                          Moderators
                          wrote on last edited by JKSH
                          #21

                          @jars121 said in Optimal way to establish large number of QTimers:

                          while (1)
                          {
                              timeStamp = currentTime();
                              //do stuff
                          
                              sleep((1/pollFrequency)-(currentTime() - timeStamp));
                          }
                          

                          With this approach, you might discover that your actual poll frequency is less than your specified poll frequency. This is because sleep(x) does not guarantee that your thread will sleep for exactly x. The actual sleep time is >= x, depending on the system load and priorities.

                          To compensate for potential extra delays, compare against the global start time instead (below is pseudo-code):

                          pollPeriod = 1000/pollFrequency; // freq in Hz, period in ms
                          startTime = currentTime(); // ms
                          
                          while (true)
                          {
                              //do stuff
                              msleep( (currentTime()-startTime) % pollPeriod );
                          }
                          

                          Furthermore, QElapsedTimer can simplify your time calculations nicely:

                          pollPeriod = 1000/pollFrequency;
                          QElapsedTimer t;
                          t.start()
                          
                          while (true)
                          {
                              //do stuff
                              msleep( t.elapsed() % pollPeriod );
                          }
                          

                          One last warning: This approach requires 1000/pollFrequency to be an integer number of milliseconds. If it's not, you still won't get your desired frequency.

                          Further reading:

                          • https://www.mail-archive.com/interest@qt-project.org/msg28783.html
                          • http://en.cppreference.com/w/cpp/thread/sleep_for
                          • http://en.cppreference.com/w/cpp/thread/sleep_until

                          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                          1 Reply Last reply
                          1
                          • J Offline
                            J Offline
                            jars121
                            wrote on last edited by
                            #22

                            That's great, thank you @JKSH !

                            I'll do some testing on this over the coming couple of days. The only issue I can foresee is in the integer requirement of the pollPeriod (1000/pollFrequency). I can enforce this by restricting the user-selectable poll frequencies available, but want to allow a highly flexible selection if possible. As such, I might need to sacrifice absolute frequency precision by rounding up/down to the nearest integer. Unless there's a comparable method which uses floats...

                            JKSHJ 1 Reply Last reply
                            0
                            • J jars121

                              That's great, thank you @JKSH !

                              I'll do some testing on this over the coming couple of days. The only issue I can foresee is in the integer requirement of the pollPeriod (1000/pollFrequency). I can enforce this by restricting the user-selectable poll frequencies available, but want to allow a highly flexible selection if possible. As such, I might need to sacrifice absolute frequency precision by rounding up/down to the nearest integer. Unless there's a comparable method which uses floats...

                              JKSHJ Offline
                              JKSHJ Offline
                              JKSH
                              Moderators
                              wrote on last edited by
                              #23

                              You're welcome!

                              @jars121 said in Optimal way to establish large number of QTimers:

                              The only issue I can foresee is in the integer requirement of the pollPeriod (1000/pollFrequency).

                              I guess if you don't mind a little bit of jitter, you could code in in such a way that the loop sleeps for, say, 33 ms most of the time but 34 ms sometimes if you want pollFrequency=30 Hz (so pollPeriod = 33.333... ms).

                              Someone mentioned this at https://www.mail-archive.com/interest@qt-project.org/msg28783.html -- read through the whole thread.

                              I can enforce this by restricting the user-selectable poll frequencies available, but want to allow a highly flexible selection if possible. As such, I might need to sacrifice absolute frequency precision by rounding up/down to the nearest integer.

                              You could ask the user to specify period instead of frequency. That gives you maximum flexibility without having to worry about rounding errors.

                              Unless there's a comparable method which uses floats...

                              1000/30 cannot be represented exactly as a floating-point number. The value will be close to, but not equal to 33.333...

                              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                              1 Reply Last reply
                              1
                              • J jars121

                                Thank you both, much appreciated as always. The 1ms aspect isn't a hard requirement, more a 'best case' if the CPU is able to support it. I now understand your approach, regarding moving of the QObject to the thread rather than the QTimer itself.

                                Having said that, I'm more inclined to put the acquisition functions in a loop on its thread as you mentioned. I'll take a timestamp at the start of each iteration of the loop, and then sleep for a calculated period of time at the end of the loop, based on the current time, the beginning time and the desired poll frequency. E.g.:

                                while (1)
                                {
                                    timeStamp = currentTime();
                                    //do stuff
                                
                                    sleep((1/pollFrequency)-(currentTime() - timeStamp));
                                }
                                

                                I'll give this approach a go and play with frequencies to see what the CPU can handle.

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on last edited by kshegunov
                                #24

                                I still don't understand why you'd want to dedicate a whole thread only to do this endless loop, as I mentioned, polling (which is the worst way you can get data from somewhere) needs no high precision or stability on the interval. If it does, then you need to use an API which actually provides asynchronous data transfer, and not polling. If your API doesn't have this, well then you're somewhat stuck ... and I know the feeling, I hope you don't think I'm just criticizing polling just for kicks.

                                Furthermore sleep and its variants can't be interrupted, which is rather notorious. So how do you exit that endless loop? Killing the thread is not an option, so you must wait for the sleep to exit and only then handle the quitting. And if your application is hanging there waiting for the sleep to finish and the OS is doing its shutdown sequence, the latter might just decide to kill the process anyway, as it's not responding ... quite the vicious circle ...

                                If you really, really need to sleep in a thread, you should do it cleverly, so you can at any time break the sleep and do shutdown/cleanup/w/e. To that end you can use QSemaphore off-label, consider the following:

                                // ... time calculations and such
                                
                                QSemaphore semaphore;
                                while (true)
                                {
                                    if (semaphore.tryAcquire(1, timeToSleep))
                                        break; // Oh-oh we were woken up in the middle of our nap to break the loop and quit (!) 
                                
                                    // ... timeToSleep milliseconds have passed
                                }
                                

                                Now you can break the sleep at any one time from the main thread by calling semaphore.release(). If you do this with a signal-slot invocation, then you need to make sure you use Qt::DirectConnection.

                                My original advice still stands though - use a QTimer.

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply
                                3
                                • J Offline
                                  J Offline
                                  jars121
                                  wrote on last edited by
                                  #25

                                  Following @kshegunov 's post, I've implemented a QTimer approach, using a dedicated QObject moved to separate threads, as per @ambershark 's post above.

                                  One question, in ambershark's example, the SLOT() is within the handler class, and simply prints the threadId after each timeout. I've got this method working in my application. How can I use a SLOT() within my main class (from where the QThread and QTimer are established)? My understanding is that the connect call can't see the main class SLOTS, as they're external to the handler QObject class.

                                  In that case, would I still use a SLOT() in the handler class, and simply redirect to a public function in the main class?

                                  jsulmJ 1 Reply Last reply
                                  0
                                  • J jars121

                                    Following @kshegunov 's post, I've implemented a QTimer approach, using a dedicated QObject moved to separate threads, as per @ambershark 's post above.

                                    One question, in ambershark's example, the SLOT() is within the handler class, and simply prints the threadId after each timeout. I've got this method working in my application. How can I use a SLOT() within my main class (from where the QThread and QTimer are established)? My understanding is that the connect call can't see the main class SLOTS, as they're external to the handler QObject class.

                                    In that case, would I still use a SLOT() in the handler class, and simply redirect to a public function in the main class?

                                    jsulmJ Offline
                                    jsulmJ Offline
                                    jsulm
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #26

                                    @jars121 If you're calling connect() in your main class then you can use slots from main class there as they are part of that class. Or do I misunderstand your question?

                                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    J 1 Reply Last reply
                                    1
                                    • jsulmJ jsulm

                                      @jars121 If you're calling connect() in your main class then you can use slots from main class there as they are part of that class. Or do I misunderstand your question?

                                      J Offline
                                      J Offline
                                      jars121
                                      wrote on last edited by
                                      #27

                                      @jsulm said in Optimal way to establish large number of QTimers:

                                      @jars121 If you're calling connect() in your main class then you can use slots from main class there as they are part of that class. Or do I misunderstand your question?

                                      You understand the question perfectly. That was my understanding as well. I have a public slot defined in my main header:

                                      //main.h
                                      
                                      public slots:
                                          void analogTimeout();
                                          void digitalTimeout();
                                      
                                      

                                      In my main.cpp file, I then establish the QThreads() and TimerHandlers() as per @ambershark 's earlier post:

                                      //main.cpp
                                      
                                      QThread* analogThread = new QThread();
                                      TimerHandler *analogTimerHandler = new TimerHandler();
                                      analogTimerHandler->moveToThread(analogThread);
                                      QTimer *analogTimer = new QTimer();
                                      analogTimer->setInterval(1000);
                                      connect(analogTimer, SIGNAL(timeout()), analogTimerHandler, SLOT(analogTimeout()));
                                      analogThread->start();
                                      analogInputTimer->start();
                                      

                                      This results in the following error:

                                      QObject::connect: No such slot TimerHandler::analogTimeout() in ../app/main.cpp:100
                                      

                                      The above error is what sparked my question. The context for the QObject::connect appears wrong. I'm calling connect() from within main.cpp, but the slot context is within the TimerHandler class.

                                      I imagine I'm overlooking something simple...

                                      jsulmJ 2 Replies Last reply
                                      0
                                      • J jars121

                                        @jsulm said in Optimal way to establish large number of QTimers:

                                        @jars121 If you're calling connect() in your main class then you can use slots from main class there as they are part of that class. Or do I misunderstand your question?

                                        You understand the question perfectly. That was my understanding as well. I have a public slot defined in my main header:

                                        //main.h
                                        
                                        public slots:
                                            void analogTimeout();
                                            void digitalTimeout();
                                        
                                        

                                        In my main.cpp file, I then establish the QThreads() and TimerHandlers() as per @ambershark 's earlier post:

                                        //main.cpp
                                        
                                        QThread* analogThread = new QThread();
                                        TimerHandler *analogTimerHandler = new TimerHandler();
                                        analogTimerHandler->moveToThread(analogThread);
                                        QTimer *analogTimer = new QTimer();
                                        analogTimer->setInterval(1000);
                                        connect(analogTimer, SIGNAL(timeout()), analogTimerHandler, SLOT(analogTimeout()));
                                        analogThread->start();
                                        analogInputTimer->start();
                                        

                                        This results in the following error:

                                        QObject::connect: No such slot TimerHandler::analogTimeout() in ../app/main.cpp:100
                                        

                                        The above error is what sparked my question. The context for the QObject::connect appears wrong. I'm calling connect() from within main.cpp, but the slot context is within the TimerHandler class.

                                        I imagine I'm overlooking something simple...

                                        jsulmJ Offline
                                        jsulmJ Offline
                                        jsulm
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #28

                                        @jars121 analogTimeout() is a slot in main class not in TimerHandler, right?

                                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        1 Reply Last reply
                                        0
                                        • J jars121

                                          @jsulm said in Optimal way to establish large number of QTimers:

                                          @jars121 If you're calling connect() in your main class then you can use slots from main class there as they are part of that class. Or do I misunderstand your question?

                                          You understand the question perfectly. That was my understanding as well. I have a public slot defined in my main header:

                                          //main.h
                                          
                                          public slots:
                                              void analogTimeout();
                                              void digitalTimeout();
                                          
                                          

                                          In my main.cpp file, I then establish the QThreads() and TimerHandlers() as per @ambershark 's earlier post:

                                          //main.cpp
                                          
                                          QThread* analogThread = new QThread();
                                          TimerHandler *analogTimerHandler = new TimerHandler();
                                          analogTimerHandler->moveToThread(analogThread);
                                          QTimer *analogTimer = new QTimer();
                                          analogTimer->setInterval(1000);
                                          connect(analogTimer, SIGNAL(timeout()), analogTimerHandler, SLOT(analogTimeout()));
                                          analogThread->start();
                                          analogInputTimer->start();
                                          

                                          This results in the following error:

                                          QObject::connect: No such slot TimerHandler::analogTimeout() in ../app/main.cpp:100
                                          

                                          The above error is what sparked my question. The context for the QObject::connect appears wrong. I'm calling connect() from within main.cpp, but the slot context is within the TimerHandler class.

                                          I imagine I'm overlooking something simple...

                                          jsulmJ Offline
                                          jsulmJ Offline
                                          jsulm
                                          Lifetime Qt Champion
                                          wrote on last edited by jsulm
                                          #29

                                          @jars121 said in Optimal way to establish large number of QTimers:

                                          The context for the QObject::connect appears wrong. I'm calling connect() from within main.cpp, but the slot context is within the TimerHandler class.

                                          This is wrong. It doesn't matter where you call connect. The slot you pass to it belongs to the object you pass to it as well. That means analogTimeout() must be a slot in TimerHandler, not in main.

                                          // SIGNAL(timeout()) - belongs to analogTimer
                                          // SLOT(analogTimeout()) - belongs to analogTimerHandler
                                          connect(analogTimer, SIGNAL(timeout()), analogTimerHandler, SLOT(analogTimeout()));
                                          

                                          If you want to connect your main then do

                                          connect(analogTimer, SIGNAL(timeout()), this, SLOT(analogTimeout()));
                                          

                                          Or if slot should really be part of AnalogTimerHandler then move it there.

                                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                                          1 Reply Last reply
                                          2

                                          • Login

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