如何从 Qt 中的工作线程 class 启动计时器?
How to start timers from the worker thread class in Qt?
控制器的声明部分class:
class ProtocolPacket: public QQuickItem
{
private:
Q_OBJECT
...
QThread objWorkerThread;
public:
ProtocolPacket();
~ProtocolPacket();
...
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();
}
工作线程的构造函数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);
}
我收到错误消息:
QObject::startTimer: Timers cannot be started from another thread
我做错了什么?
我希望从 worker class 启动计时器:ReadWriteSerialPort
在移动到另一个线程的对象中构造的每个对象都必须设置其父对象:
class ReadWriteSerialPort : public QObject {
QSerialPort serialPort { this }; // important
QTimer timerSendVelocityPackets { this }; // etc.
...
};
您还必须确保 没有从其他线程直接调用 ReadWriteSerialPort
的线程不安全方法。
此外,除非您正在轮询数据,否则定时器驱动的数据包接收是不正确的。你应该对串口发出的readyRead
信号进行操作。
我也质疑单独的 reader 和作者:通常这些任务都需要知道目标设备的预期状态,所以将它们分开可能没有帮助。没有看到更多代码就很难说。
控制器的声明部分class:
class ProtocolPacket: public QQuickItem
{
private:
Q_OBJECT
...
QThread objWorkerThread;
public:
ProtocolPacket();
~ProtocolPacket();
...
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();
}
工作线程的构造函数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);
}
我收到错误消息:
QObject::startTimer: Timers cannot be started from another thread
我做错了什么?
我希望从 worker class 启动计时器:ReadWriteSerialPort
在移动到另一个线程的对象中构造的每个对象都必须设置其父对象:
class ReadWriteSerialPort : public QObject {
QSerialPort serialPort { this }; // important
QTimer timerSendVelocityPackets { this }; // etc.
...
};
您还必须确保 没有从其他线程直接调用 ReadWriteSerialPort
的线程不安全方法。
此外,除非您正在轮询数据,否则定时器驱动的数据包接收是不正确的。你应该对串口发出的readyRead
信号进行操作。
我也质疑单独的 reader 和作者:通常这些任务都需要知道目标设备的预期状态,所以将它们分开可能没有帮助。没有看到更多代码就很难说。