QSerialPort and QThread
-
Hello everyone!
I still trying to learn how to use QSerialPort correctly. And I am getting new problems.
I create QThread in some PARENT class:
thread = new QThread; // Create QThread task = new ThreadClass; // CHILD class, in which I have methods for reading and writing data with QSerialPort task->moveToThread(thread); // Move needed class to created thread connect(thread, SIGNAL(started()), task, SLOT(writeData_slot()); // Connect to writeData_slot() method, when I will start the thread
and I have in this PARENT class another method, where I want to start or stop (now there is while cycle for check) the thread:
if (isConnected) { thread->start(); } else { int count = 0; while (count < 5) { count++; QThread::msleep(1000); qDebug("WE ARE HERE!"); } }
In CHILD class (for thread) I have two methods for reading and writing data with QSerialPort:
void Thread::readyWrite_slot() { serialPort->write(writeData); qDebug("WRITE"); QThread::msleep(1000); } void Thread::readyRead_slot() { readData.append(serialPort->readAll()); if (readData.count() == 5) { readData.clear(); qDebug("READ"); emit readyWrite_signal(); } }
connect(serialPort, &QSerialPort::readyRead, this, &Thread::readyRead_slot); connect(this, SIGNAL(readyWrite_signal()), SLOT(readyWrite_slot()));
So, I start thread and get data, but when I want to stop getting data, I want to get all data last time, but I can't:
WRITE READ // In CHILD Thread WRITE READ // In CHILD Thread WRITE READ // In CHILD Thread WRITE WE ARE HERE! // Here I want to close CHILD Thread in PARENT class WE ARE HERE! WE ARE HERE! WE ARE HERE! WE ARE HERE! READ // But only here I get my last data in CHILD Thread WRITE READ // 1 WRITE - 1 READ WRITE READ // 1 WRITE - 1 READ WRITE READ // 1 WRITE - 1 READ WRITE READ // 1 WRITE - 1 READ
It means, that thread doesn't work parallel, but it's not true, because I wrote endless while cycle in readyWrite_slot() with message, for example, and got this message together with WE ARE HERE message. Then, my conclusion, I can't get readyRead() signal for some reason, but after cycle with WE ARE HERE message I continue get readyRead() signal. I don't close SerialPort, I just execute while() cycle 5 times and all. After that thread continues to work correctly.
So, I can't stop correctly my thread, because I can't get last data, but I need it. I don't know what I can do to fix it.
Hope for your help and advice! Thank you in advance!
-
@jsulm said in QSerialPort and QThread:
@oBOXPOH My first question: why do you need a thread? QSerialPort is asynchronous - there is usually no need for a thread.
Because I need to represent my data parallel without losing of control in PARENT class, where I have some buttons, for example.
-
-
@JonB said in QSerialPort and QThread:
@oBOXPOH
Don't understand what you mean here. As @jsulm says,QSerialPort
is asynchronous, you just don't usually need a thread, why do you need one? If you mean you are passing a parent to yourQSerialPort
which then goes out of scope taking the port with it, then don't use that parent!I can use call to method for writing data instead of creating thread:
if (isConnected) { //thread->start(); task->readyWrite_slot(); }
but then I get only one WRITE message and no more, i.e. I can't reach method for reading.
-
@JonB said in QSerialPort and QThread:
@oBOXPOH
Then if you have some "ready write" slot you can also write a "ready read" slot, https://doc.qt.io/qt-5/qiodevice.html#readyRead.See before, I have it.
void Thread::readyRead_slot() { readData.append(serialPort->readAll()); if (readData.count() == 5) { readData.clear(); qDebug("READ"); emit readyWrite_signal(); } }
Thread is just class. I don't use it like QThread. And I haven't readyRead() signal.
-
@oBOXPOH said in QSerialPort and QThread:
Then, my conclusion, I can't get readyRead() signal for some reason
Yes, of course, you're calling QThread::Sleep all over the place. Every time you call that, no Signals will be processed, until the sleep is over.
I highly doubt, that you're programming (with Qt) for a micro controller -> do not use QThread::Sleep, at all.
-
@J-Hilk said in QSerialPort and QThread:
@oBOXPOH said in QSerialPort and QThread:
Then, my conclusion, I can't get readyRead() signal for some reason
Yes, of course, you're calling QThread::Sleep all over the place. Every time you call that, no Signals will be processed, until the sleep is over.
I highly doubt, that you're programming (with Qt) for a micro controller -> do not use QThread::Sleep, at all.
Oh, it's, I think, really useful answer! Thank you! But can you then, please, tell me what I need to use to make some delay?
-
@oBOXPOH
That really depends on your situation, but one usually uses QTimer, or more conveniently one of the static single Shot variants for example
https://doc.qt.io/qt-5/qtimer.html#singleShot -
@J-Hilk said in QSerialPort and QThread:
@oBOXPOH
That really depends on your situation, but one usually uses QTimer, or more conveniently one of the static single Shot variants for example
https://doc.qt.io/qt-5/qtimer.html#singleShotIt's really bad, if another good way isn't exists.
Because developer needs to write such things instead of some sleep string:
QTimer::singleShot(100, this, SLOT(slot()));
and developer need to create slot() method, where he writes all actions, which he want to execute after 100ms delay. And it's bad, if you want to make delay not in thread, because in thread you can use:
QThread::currentThread()->msleep(100);
and not in thread - thing before with singleShot() method. I hope, I am wrong.
-
@oBOXPOH
It's not "bad". Signals/slots/event-driven is a different architectural design from linear "sleep" approach. Many SDKs or languages use this approach these days, it has its advantages.Experts may not thank me for mentioning this, but if you really want to you may be able to use a "sleep"-type and still allow signals/slots/events if you use
QEventLoop
+QTimer
in your thread. You'd have to try it. -
@oBOXPOH You are using an event driven framework (Qt is not the only one by the way). In such frameworks you should never block the event loop with long lasting loops and sleep() calls. This is simply working against the framework.