QSerialPort discovery in a non GUI QThread?
-
@JonB Hi, I need
bool QSerialPort::waitForReadyRead(int msecs)
to verify that I am connecting to the correct MCU. My MCUs are programmed to send a special text over the Serial Port as soon as the communication is established with it.
If I do not use thebool QSerialPort::waitForReadyRead(int msecs)
then I will have to connect to all the MCUs where the vendor and product identifiers are the same (which can be multiple from my own hardware) and then wait to receive a signal back and somehow verify the correct one and then break and re-establish the correct connection. All this will take time and in between if the user plugs or unplugs something then my entire calculation for finding the correct MCU will be wrong and it will be a mess. -
@CJha
You never needwaitForReadyRead()
. Like I said it's only a wrapper on top of the signal to make it block and wait. It is implemented as something like (https://codebrowser.dev/qt5/qtserialport/src/serialport/qserialport_unix.cpp.html#_ZN18QSerialPortPrivate16waitForReadyReadEi):while (QElapsedTimer.elapsed()) qt_poll_msecs()
No reason why you cannot do this without the
QEventLoop
/waitFor...()
.and it will be a mess.
Your current code is a mess because it does not deal with the secondary thread correctly.
-
Your current code is a mess because it does not deal with the secondary thread correctly.
It is dealing with the secondary thread correctly, the secondary thread is created and destroyed without any issues or memory leaks, and the communication with the secondary thread is all based on signal-slot mechanism and is of type
Qt::QueuedConnection
. Thread is not the problem the problem is the limitations of theQSerialPort
.I will try the
QEventLoop
method, but it will need a timeout because of how the serial communication happens. -
@CJha said in QSerialPort discovery in a non GUI QThread?:
It is dealing with the secondary thread correctly,
Approach 1:
QObject: Cannot create children for a parent that is in a different thread.
Approach 2:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread.
Your definition of "dealing with the secondary thread correctly" is different from mine then.
Since you already know you are right and it needs a secondary thread with
waitFor...()
rather than the normal Qt asynchronous approach withreadyRead()
signal and non-blocking slot there is not much for me to say, so I leave you to it. -
You are only taking half of the warning/error messages, the rest of it says:
Approach 1:
(Parent is
QSerialPort
(0xf037eff560), parent's thread is QThread(0x2b741fdbf30), current thread is QThread(0x2b741ff38d0)Approach 2:
Current thread 0x0x16d3dbc2c50. Receiver '' (of type '
QSerialPort
') was created in thread 0x0x16d3dbd8d00"And I mentioned
Thread is not the problem the problem is the limitations of the QSerialPort.
In both cases
QSerialPort
is causing the issue, if I take it out and replace it with a simpleQObject
then the threads are fine. So how is dealing with the thread an issue here? As you mentioned:Your current code is a mess because it does not deal with the secondary thread correctly.
Sure putting
QSerialPort
in a thread can be an issue but the thread itself is not an issue. That's all I am trying to point out. -
@CJha There are a couple of issues with both of your approaches, I assume because you're laking some knowledge about QThread and or QSerialPort.
That is fine, no-one can know everything.I'll help you fix the jamming of the gun, but I lack the time and patience these days to show you all the ins and outs of gun safety.
:
give your SerialPort instance the correct parent instead of noneMCU::MCU(QObject *parent) : QObject(parent), port(this) {
-
@CJha
For the record. You will see I changed my post above to show whatQSerialPort::waitForReadyRead()
seems to use in its code. This is not theQEventLoop
guess which I originally entered.QEventLoop
plays better with not blocking the UI than that code. I do not know whywaitForReadyRead()
does not seem to use that, or how you using that differs from what they do. -
@JonB Yes I noticed the change. I am not sure why they do it the way they are doing it. I am starting a single shot timer and immediately after I am starting the event loop which exits with exit code 1 with the
readyRead()
signal received or with exit code 0 if the timer runs out. If I have the exit code of 1 I read the port and start the process again till the exit code of 0 is received. Seems simple and works every time.