Solved 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 socketsocket->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.
-
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 wayvoid 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 inm_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 thatm_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 withQTimer::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.