[Solved] QtSerialPort and Threads
-
Hi, Thanks kuzulis.
I thought of using threads and blocking approach because if I'm processing received data i can't do anything else in my gui.
As i mentioned i need to receive data, update gui, do some calculations and write back to pic. And i think that if i use async approach in guithread my app will be most of the time processing reception. Also i will receive data from another serial device.
-
UPD:
bq. I need to receive a data array, from a PIC18F, for example: 0 | 1 | 3 | 121 | 50 | 99 other is 0 | 2 | 2 | 10 | 150
bq. to detect the start i use 0, then message identifier (1 or 2), next the number of data bytes and finally the data bytes (data will change).
I don't understand that to you is unclear?
@
...
enum ParserState { WaitForStart, WaitForMsgId, WaitForData, Done };static ParserState currentParserState = WaitForStart; // start synchronization
......
connect(port, SIGNAL(readyRead()), this, SLOT(onParseInputStream()));
...SerialPortHandlingLayer::onParseInputStream()
{
while (port->bytesAvailable() > 0) {
switch (currentParserState) {
case WaitForStart:
char c = 0;
if (port->peek(&c, 1) > 0 && (c == 0)) {
currentParserState = WaitForMsgId;
} else {
// read wrong char to dummy, skip it
port->read(&c, 1);
// stay on WaitForStart
}
break;case WaitForMsgId: QByteArray ba = port->peek(2); if (ba.at(1) == 1 ||ba.at(1) == 2) { currentParserState = WaitForData; } else { // read wrong char to dummy, skip it port->read(&c, 1); // transition to WaitForStart currentParserState = WaitForStart; } break; case WaitForData: // parse next length field from data QByteArray ba = port->peek(3); int msgLength = ba.at(2); if (msgLength <= port->bytesAvailable() - 2) { // all complete data is available // skip start, id, length field QByteArray dummy = port->read(3); // read complete data QByteArray data = port->read(msgLength); emit port->completeData(data); } else { // not all data is available, wait for next readyRead() return; } break; } }
}
@
-
This part i already have working.
The problem is that while i'm doing reception i can't do anything else. -
You can do the calculations (parse or something else) in a separate thread (e.g. using QtConcurrent) and pass the result of the calculations through the signal to the QtSerialPort back. So, I not see a problem.
-
Then don't block: read what is available on the port in a QByteArray and once the QByteArray has the correct size, do your computation.
Between two readyRead, your GUI will be responsive.
-
Hi, I will try your approach, but i will need to receive data from another serialport. How can i do this? Because if i'm processing the readyRead() of the first, my app can't process the readyRead() of the second...
That's why i first thought about threads.. -
Sorry? You give us all new and new surprises? :)
bq. Hi, I will try your approach, but i will need to receive data from another serialport. How can i do this?
This:
@
QSerialPort *port1 = new QSerialPort;
QSerialPort *port2 = new QSerialPort;connect(port1, SIGNAL(readyRead()),
this, SLOT(onReadyReadFromPort1()));connect(port2, SIGNAL(readyRead()),
this, SLOT(onReadyReadFromPort2()));port1->setPortName("COM1");
port2->setPortName("COM125");...
...
...
@does not work? :)
-
I already had mentioned it in a previous post.
I thought of doing like you say, but my question is: if both signals happen at same time, won't my program freeze? It will only process one or the other, or so i think... Or can 2 slots be processed at the same time?
-
bq. if both signals happen at same time, won’t my program freeze?
It depends on the code that you implement in the handler of each slot.
bq. Or can 2 slots be processed at the same time?
Any slot/signal is executed in turn in a context of the current thread. Only one slot it is possible to process at the same time. Signals can't come at the same time, all (signals and slots) is processing from Qt event-loop queue (as a whole).
Please, read documentation on Qt as a whole...
-
Ok, like i thought.
That's why i first thought on using Threads...
So that each serialport could only deal with one port.