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. A thread execution problem.
Forum Updated to NodeBB v4.3 + New Features

A thread execution problem.

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 383 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.
  • J Offline
    J Offline
    jenya7
    wrote on last edited by jenya7
    #1

    I have a widget application.

    int main(int argc, char *argv[])
    {
        QThread main_thread; 
        worker *m_worker = new worker();
        m_worker->moveToThread(&main_thread);
    
        QApplication a(argc, argv);
    
        MainWindow w;
        w.show();
    
           QObject::connect(&main_thread, &QThread::started, m_worker, &worker::Process);
        QObject::connect(m_worker, &worker::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
    
        QObject::connect(&m_sys, &SYS::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
        QObject::connect(&m_comparser, &COMPARSER::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
        QObject::connect(&m_commands, &COMMANDS::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
        QObject::connect(&m_master, &master::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
        QObject::connect(&m_sensor, &SENSOR::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
        QObject::connect(&m_script, &SCRIPT::SendMessage, &w, &MainWindow::DisplayScriptMessage);
    
        //load the default parameters and script
        sys_params_file = QCoreApplication::applicationDirPath() + "/sys_params.xml";
        script_file = QCoreApplication::applicationDirPath() + "/script.txt";
    
        m_sys.ParamInit(sys_params_file);
    
        m_script.Init(script_file);
    
        main_thread.start();
    
        return a.exec();
    }
    

    I need some tasks to run constantly, so I create a thread

    QThread main_thread; 
    worker *m_worker = new worker();
    m_worker->moveToThread(&main_thread);
    

    In the thread it looks like this

    __attribute__ ((noreturn)) void worker::Process()
    {
        while (1)
        {
              m_script.Run();
        }
    }
    

    I set a brake point at - m_script.Run(); - and it's OK - I get there immediately.
    But when I connect a udp socket

    socket->bind(QHostAddress(local_ip), local_port);
    

    I get to the line - m_script.Run(); every 8-10 seconds. It looks like it breaks from the while loop, goes somewhere and returns. And remote sensors get messages every 8-10 seconds. What generates the delay? I use the udp socket in - m_script.Run(); - may be cross thread access? If so - how to avoid it?

    KroMignonK 1 Reply Last reply
    0
    • J jenya7

      I have a widget application.

      int main(int argc, char *argv[])
      {
          QThread main_thread; 
          worker *m_worker = new worker();
          m_worker->moveToThread(&main_thread);
      
          QApplication a(argc, argv);
      
          MainWindow w;
          w.show();
      
             QObject::connect(&main_thread, &QThread::started, m_worker, &worker::Process);
          QObject::connect(m_worker, &worker::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
      
          QObject::connect(&m_sys, &SYS::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
          QObject::connect(&m_comparser, &COMPARSER::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
          QObject::connect(&m_commands, &COMMANDS::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
          QObject::connect(&m_master, &master::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
          QObject::connect(&m_sensor, &SENSOR::SendMessage, &w, &MainWindow::DisplayTerminalMessage);
          QObject::connect(&m_script, &SCRIPT::SendMessage, &w, &MainWindow::DisplayScriptMessage);
      
          //load the default parameters and script
          sys_params_file = QCoreApplication::applicationDirPath() + "/sys_params.xml";
          script_file = QCoreApplication::applicationDirPath() + "/script.txt";
      
          m_sys.ParamInit(sys_params_file);
      
          m_script.Init(script_file);
      
          main_thread.start();
      
          return a.exec();
      }
      

      I need some tasks to run constantly, so I create a thread

      QThread main_thread; 
      worker *m_worker = new worker();
      m_worker->moveToThread(&main_thread);
      

      In the thread it looks like this

      __attribute__ ((noreturn)) void worker::Process()
      {
          while (1)
          {
                m_script.Run();
          }
      }
      

      I set a brake point at - m_script.Run(); - and it's OK - I get there immediately.
      But when I connect a udp socket

      socket->bind(QHostAddress(local_ip), local_port);
      

      I get to the line - m_script.Run(); every 8-10 seconds. It looks like it breaks from the while loop, goes somewhere and returns. And remote sensors get messages every 8-10 seconds. What generates the delay? I use the udp socket in - m_script.Run(); - may be cross thread access? If so - how to avoid it?

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #2

      @jenya7 said in A thread execution problem.:

      while (1)
      {
      m_script.Run();
      }

      Doing this, you are blocking the event loop, which means no signals/slots can be handled.
      So sockets (and other signals/slots based classes) leaving in that thread, can not work properly.

      Take a look at:

      • https://wiki.qt.io/Threads_Events_QObjects
      • https://doc.qt.io/qt-5.12/threads-qobject.html

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      J 1 Reply Last reply
      0
      • KroMignonK KroMignon

        @jenya7 said in A thread execution problem.:

        while (1)
        {
        m_script.Run();
        }

        Doing this, you are blocking the event loop, which means no signals/slots can be handled.
        So sockets (and other signals/slots based classes) leaving in that thread, can not work properly.

        Take a look at:

        • https://wiki.qt.io/Threads_Events_QObjects
        • https://doc.qt.io/qt-5.12/threads-qobject.html
        J Offline
        J Offline
        jenya7
        wrote on last edited by jenya7
        #3

        @KroMignon
        I created a thread (as it was suggested in the link)

        //h
        #ifndef MYTHREAD_H
        #define MYTHREAD_H
        
        #include <QThread>
        
        class MyThread : public QThread
        {
            public:
            MyThread();
        
            void run();
        };
        
        #endif // MYTHREAD_H
        
        
        //cpp
        #include "mythread.h"
        #include "script.h"
        #include "sys.h"
        
        MyThread::MyThread()
        {
        
        }
        void MyThread::run()
        {
                m_script.Run();
        }
        

        In main

        MyThread *thr = new MyThread;
        thr->run();
        

        It goes to m_script.Run(); only once.

        J.HilkJ KroMignonK 2 Replies Last reply
        0
        • J jenya7

          @KroMignon
          I created a thread (as it was suggested in the link)

          //h
          #ifndef MYTHREAD_H
          #define MYTHREAD_H
          
          #include <QThread>
          
          class MyThread : public QThread
          {
              public:
              MyThread();
          
              void run();
          };
          
          #endif // MYTHREAD_H
          
          
          //cpp
          #include "mythread.h"
          #include "script.h"
          #include "sys.h"
          
          MyThread::MyThread()
          {
          
          }
          void MyThread::run()
          {
                  m_script.Run();
          }
          

          In main

          MyThread *thr = new MyThread;
          thr->run();
          

          It goes to m_script.Run(); only once.

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #4

          @jenya7

          void MyThread:.doStuff()
          {
              m_script.Run();
          }
          
          void MyThread::run()
          {
                 QTimer timer;
                 connect(&timer, &QTimer::timeout, this, &MyThread::doStuff);
                 timer.start(0);
                 exec();
          }
          

          Somehow I got the feeling you shouldn't use threads...


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          2
          • J jenya7

            @KroMignon
            I created a thread (as it was suggested in the link)

            //h
            #ifndef MYTHREAD_H
            #define MYTHREAD_H
            
            #include <QThread>
            
            class MyThread : public QThread
            {
                public:
                MyThread();
            
                void run();
            };
            
            #endif // MYTHREAD_H
            
            
            //cpp
            #include "mythread.h"
            #include "script.h"
            #include "sys.h"
            
            MyThread::MyThread()
            {
            
            }
            void MyThread::run()
            {
                    m_script.Run();
            }
            

            In main

            MyThread *thr = new MyThread;
            thr->run();
            

            It goes to m_script.Run(); only once.

            KroMignonK Offline
            KroMignonK Offline
            KroMignon
            wrote on last edited by
            #5

            @jenya7 said in A thread execution problem.:

            It goes to m_script.Run(); only once.

            Of course it will be called only once. It is what you have coded!
            Please take time to understand what you are doing.

            As written before, QObject based classes requires a working event queue to handle the signals/slots connections.
            Signals are handled in the eventloop attached to the thread used by the class instance.
            To be able to do so, the eventloop should not be blocked. Which means no forever loops or active waits.

            Your first code was not that bad... Simple think more in Qt way.

            void worker::Process()
            {
                // run the script
                m_script.Run()
                // recall worker::Process() ASAP
                QTimer::singleShot( 0, this, &worker::Process);
            }
            

            I don't know what you are doing in m_script.Run().
            Qt is an asynchronous framework, never forget this and avoid forever loop / active wait when you are using QObject based classes.

            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

            J 1 Reply Last reply
            0
            • KroMignonK KroMignon

              @jenya7 said in A thread execution problem.:

              It goes to m_script.Run(); only once.

              Of course it will be called only once. It is what you have coded!
              Please take time to understand what you are doing.

              As written before, QObject based classes requires a working event queue to handle the signals/slots connections.
              Signals are handled in the eventloop attached to the thread used by the class instance.
              To be able to do so, the eventloop should not be blocked. Which means no forever loops or active waits.

              Your first code was not that bad... Simple think more in Qt way.

              void worker::Process()
              {
                  // run the script
                  m_script.Run()
                  // recall worker::Process() ASAP
                  QTimer::singleShot( 0, this, &worker::Process);
              }
              

              I don't know what you are doing in m_script.Run().
              Qt is an asynchronous framework, never forget this and avoid forever loop / active wait when you are using QObject based classes.

              J Offline
              J Offline
              jenya7
              wrote on last edited by
              #6

              @KroMignon
              Thank you. But this way

              void worker::Process()
              {
                  // run the script
                  m_script.Run()
                  // recall worker::Process() ASAP
                  QTimer::singleShot( 0, this, &worker::Process);
              }
              

              I get the same result - after UDP socket connection it gets to m_script.Run() every 8-10 seconds.
              In m_script.Run() I parse a script, not much complicated, the only cross operation - sending some short messages on the UDP socket.

              KroMignonK 1 Reply Last reply
              0
              • J jenya7

                @KroMignon
                Thank you. But this way

                void worker::Process()
                {
                    // run the script
                    m_script.Run()
                    // recall worker::Process() ASAP
                    QTimer::singleShot( 0, this, &worker::Process);
                }
                

                I get the same result - after UDP socket connection it gets to m_script.Run() every 8-10 seconds.
                In m_script.Run() I parse a script, not much complicated, the only cross operation - sending some short messages on the UDP socket.

                KroMignonK Offline
                KroMignonK Offline
                KroMignon
                wrote on last edited by
                #7

                @jenya7 said in A thread execution problem.:

                In m_script.Run() I parse a script, not much complicated, the only cross operation - sending some short messages on the UDP socket.

                Again, I don't know what you mean with not much complicated, but to work QUdpSocket needs a working event loop.
                If you are blocking the event queue used by the socket, no message will be send/received.

                It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                J 1 Reply Last reply
                0
                • KroMignonK KroMignon

                  @jenya7 said in A thread execution problem.:

                  In m_script.Run() I parse a script, not much complicated, the only cross operation - sending some short messages on the UDP socket.

                  Again, I don't know what you mean with not much complicated, but to work QUdpSocket needs a working event loop.
                  If you are blocking the event queue used by the socket, no message will be send/received.

                  J Offline
                  J Offline
                  jenya7
                  wrote on last edited by jenya7
                  #8

                  @KroMignon
                  The targets get the messages. And I get replies from it. The only problem - it executes every 8-10 seconds. And GUI isn't stuck, it runs fluently.
                  Actually right now the only socket user is m_script.Run().
                  I wonder what can distract worker::Process() from execution for 8-10 seconds.

                  KroMignonK 1 Reply Last reply
                  0
                  • J jenya7

                    @KroMignon
                    The targets get the messages. And I get replies from it. The only problem - it executes every 8-10 seconds. And GUI isn't stuck, it runs fluently.
                    Actually right now the only socket user is m_script.Run().
                    I wonder what can distract worker::Process() from execution for 8-10 seconds.

                    KroMignonK Offline
                    KroMignonK Offline
                    KroMignon
                    wrote on last edited by
                    #9

                    @jenya7 said in A thread execution problem.:

                    The targets get the messages. And I get replies from it. The only problem - it executes every 8-10 seconds. And GUI isn't stuck, it runs fluently.
                    Actually right now the only socket user is m_script.Run().

                    I don't understand what you are asking?
                    What is your question?

                    It is normal that the main thread is not impacted, because the worker class instance leaves in another thread. So what?
                    You have timing issues, but as I don't know what you are doing in m_script.Run(), what do you expect as reply?

                    I am not totally sure that the worker class is build as it should be.
                    As written before, when using Qt, you have to think asynchronous. This is the key word.
                    My feeling is that m_script.Run() is blocking the event loop for a long time, and all this time all the events are stored in the loop and only process after event loop is called.
                    My dirty hack with QTimer::singleShot( 0, this, &worker::Process); is not really the way I would do it is my application.
                    You should avoid to mix synchronous and asynchronous programming.
                    Using signals/slots is asynchronous, so perhaps you should rethink the way you have build your application.

                    But you are the developer, you have to know what you are doing... I guess.

                    It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                    J 1 Reply Last reply
                    2
                    • KroMignonK KroMignon

                      @jenya7 said in A thread execution problem.:

                      The targets get the messages. And I get replies from it. The only problem - it executes every 8-10 seconds. And GUI isn't stuck, it runs fluently.
                      Actually right now the only socket user is m_script.Run().

                      I don't understand what you are asking?
                      What is your question?

                      It is normal that the main thread is not impacted, because the worker class instance leaves in another thread. So what?
                      You have timing issues, but as I don't know what you are doing in m_script.Run(), what do you expect as reply?

                      I am not totally sure that the worker class is build as it should be.
                      As written before, when using Qt, you have to think asynchronous. This is the key word.
                      My feeling is that m_script.Run() is blocking the event loop for a long time, and all this time all the events are stored in the loop and only process after event loop is called.
                      My dirty hack with QTimer::singleShot( 0, this, &worker::Process); is not really the way I would do it is my application.
                      You should avoid to mix synchronous and asynchronous programming.
                      Using signals/slots is asynchronous, so perhaps you should rethink the way you have build your application.

                      But you are the developer, you have to know what you are doing... I guess.

                      J Offline
                      J Offline
                      jenya7
                      wrote on last edited by jenya7
                      #10

                      @KroMignon
                      Thank you for pointing me out.
                      I went to SCRIPT::Run and I see it takes a long time to process - some sensors don't respond and I wait some timeout (3 sec) so it accumulates to 8-10 seconds of timeout.

                      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