如何从Qt中的工作线程类启动计时器?

时间:2016-05-11 12:15:47

标签: multithreading qt timer qthread

Controller类的声明部分:

class ProtocolPacket: public QQuickItem
{
private:

    Q_OBJECT

    ...
    QThread objWorkerThread;

public:
    ProtocolPacket();
    ~ProtocolPacket();
...

控制器类的构造函数:

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();
}

工作线程类的构造函数:

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类启动计时器:ReadWriteSerialPort

1 个答案:

答案 0 :(得分:3)

在移动到另一个线程的对象中构造的每个对象都必须具有其父集:

var url = $sce.trustAsResourceUrl("http://www.w3schools.com");

您还必须确保没有直接调用来自其他线程的class ReadWriteSerialPort : public QObject { QSerialPort serialPort { this }; // important QTimer timerSendVelocityPackets { this }; // etc. ... }; 的线程不安全方法。

此外,除非您轮询数据,否则定时器驱动的数据包接收不正确。您应该对串口发出的ReadWriteSerialPort信号采取行动。

我还质疑单独的读写器:通常这些任务都需要知道目标设备的预期状态,因此将它们分开可能是无益的。没有看到更多的代码就很难说。