Declaration part of Controller class:
class ProtocolPacket: public QQuickItem
{
private:
Q_OBJECT
...
QThread objWorkerThread;
public:
ProtocolPacket();
~ProtocolPacket();
...
The constructor of controller class:
ProtocolPacket::ProtocolPacket()
{
ReadWriteSerialPort *objReadWriteSerialPort = new ReadWriteSerialPort;
objReadWriteSerialPort->moveToThread(&objWorkerThread);
connect(&objWorkerThread, &QThread::finished,
objReadWriteSerialPort, &QObject::deleteLater);
/// Following signals of ProtocolPacket class are connected to the corresponding
/// slots of thread class ReadWriteSerialPort.
connect(this, &ProtocolPacket::cameraValueChanged,
objReadWriteSerialPort, &ReadWriteSerialPort::receiveAndSendUpdatedCameraValue);
...
...
objWorkerThread.start();
}
The constructor of worker thread class:
ReadWriteSerialPort::ReadWriteSerialPort()
{
...
serialPort.setPortName ("/dev/ttyUSB0");
serialPort.setBaudRate (QSerialPort::Baud19200);
if(serialPort.open (QIODevice::ReadWrite))
{
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::NoParity);
serialPort.setStopBits(QSerialPort::OneStop);
}
objWriter = new SerialPortWriter(&serialPort);
objReader = new SerialPortReader(&serialPort);
timerSendVelocityPackets = new QTimer(this);
connect (timerSendVelocityPackets, SIGNAL (timeout()),
this, SLOT (sendVelocityPacket()));
timerSendHealthFeedbackPackets = new QTimer(this);
connect (timerSendHealthFeedbackPackets, SIGNAL (timeout()),
this, SLOT (formAndSendHealthFeedbackPackets()));
timerReceivePackets = new QTimer (this);
connect (timerReceivePackets, SIGNAL (timeout()),
this, SLOT (receiveAndUnpackPacket()));
timerReceivePackets->start (300);
}
I am receiving the error:
QObject::startTimer: Timers cannot be started from another thread
What am I doing wrong?
I wish to start the timers from the worker class: ReadWriteSerialPort
Every object constructed in the object that you move to another thread must have its parent set:
class ReadWriteSerialPort : public QObject {
QSerialPort serialPort { this }; // important
QTimer timerSendVelocityPackets { this }; // etc.
...
};
You also must ensure that there are no direct calls into the thread-unsafe methods of ReadWriteSerialPort
from other threads.
Furthermore, unless you're polling for data, the timer-driven packet receive is incorrect. You should act on the readyRead
signal issued by the serial port.
I also question the separate reader and writer: Usually these tasks both need to be aware of the expected state of the target device, so separating them might be unhelpful. It's hard to say without seeing more of the code.