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

A thread execution problem.



  • 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?



  • @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:



  • @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.


  • Moderators

    @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...



  • @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.



  • @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.



  • @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.



  • @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.



  • @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.



  • @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.


Log in to reply