Solved Non blocking console reading.
-
@KroMignon
One more question. If I install several timers - does it runs in separate threads? Do I have to worry about cross thread collisions?int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTimer timer1; QObject::connect(&timer1, &QTimer::timeout, Func1); timer1.start(1); QTimer timer2; QObject::connect(&timer2, &QTimer::timeout, Func2); timer2.start(10); return a.exec(); }
-
@jenya7
No they do not run in separate threads. In Qt only one timer signal is issued at a time, the next one cannot happen until any slot(s) attached to the first one have returned. At around 10 seconds both of your timers will timeout, in undefined order. -
@JonB said in Non blocking console reading.:
In Qt only one timer signal is issued at a time, the next one cannot happen until any slot(s) attached to the first one have returned.
Normally!
There's a (Qt) way to break that, rather easily. -
@J-Hilk
That, it seems to me, is true for any Qt signals (certain code can cause another signal to be emitted while one is still being handled). However, I took the OP's question to mean if she just does some non-Qt processing in the slots.In any case, even if the second timer signal is emitted while the first is still being handled, I don't see that is a threading issue (again, assuming, OP is not doing her own threading stuff).
-
I've experimented a bit, just to understand deeper
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFuture<void> future = QtConcurrent::run(&TerminalRead); while(1) { DoSomething(); } } __attribute__ ((noreturn)) void TerminalRead() { while (1) { ch_ptr = fgets(cons_str, 256, stdin); if (ch_ptr != nullptr) { trimmed_str = Trim(cons_str, TRIM_BOTH); COMPARSER_ParseCommand(trimmed_str); } } }
And it works quite well. I get non blocking input from console and parse it. And tasks run in the loop.
Is using QtConcurrent good practice? Does it creates a separate thread? Is it alternative to timers? -
@jenya7
Yes it creates a separate thread. That is one way of using blocking calls without blocking the main thread. I didn't want to complicate with that possibility earlier (but you seem to have dived right in there!).Be aware: I'm not sure whether C runtime calls like
fgets()
are thread-safe if you use them, or other stdio, stuff in other threads. (Answer: it is not thread-safe, unless you are using some version/library which has been rewritten to be thread-safe.) You must also be careful what you do inCOMPARSER_ParseCommand()
, as that is running in its own thread. -
@JonB
With timers it works very well. I'm glad. Thank you. -
@jenya7 said in Non blocking console reading.:
With timers it works very well. I'm glad. Thank you.
I don't think 'this works well'.
It is horrible in terms of Qt code conformity.
Please be consistent.
If you want to use Qt for developing an application, then use it in the right way or you will only be frustrated because nothing will work as expected.Again and again do not use forever loops/ active waits with Qt if you want your application to work.
-
@KroMignon
I have a discover function - it runs through all sensors and detects who is alive - I see no way but to iterate all sensors in a loop. It looks likediscover_state = DISC_ST_START; printf("Discovering...\n"); while (done == 0) { switch (discover_state) { case DISC_ST_START: data[3] = static_cast<char>(MSG_OPCODE_WHO_IS); data[2] = static_cast<char>(idx); //to a slave //reset for the next sensor new_message_flag = 0; timer.restart(); UDP_Send(data, sys_params.broadcast_ip, sys_params.remote_port); discover_state = DISC_ST_WAIT; break; case DISC_ST_WAIT: if (new_message_flag) { printf("Discovered sensor ID: %d\n", idx); discover_state = DISC_ST_NEXT; } else { millisec = timer.elapsed(); if (millisec > SENS_RESPONSE_TIME) discover_state = DISC_ST_NEXT; } break; case DISC_ST_NEXT: idx++; if (idx >= count || idx >= 254) done = 1; else discover_state = DISC_ST_START; break; } } printf("Done.\n");
May I get rid of the loop?
-
@jenya7
You are asking a very different question here.Let's go back to the original blocking/non-blocking input from console/terminal.
There are only two choices for how to approach:
-
The single-threaded (Qt) way. Cannot use a
while (true)
loop, and cannot be done with a blocking call likefgets()
. You would either have to pursue the links I posted, or change over to aQApplication
instead ofQCoreApplication
. -
The multi-threaded (not-really-Qt) way you posted. Use a thread. That can allow
fgets()
, and alsowhile (true)
: they both block, but it's OK because they are in a thread.
-
-
@JonB
Thank you. I have to process all this information. :)