2016-05-11 41 views
0

聲明部分:如何從Qt中的工作線程類啓動計時器? 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); 
} 

我receivi納克錯誤:

QObject::startTimer: Timers cannot be started from another thread

我在做什麼錯?

我要開始從工人階級定時器:ReadWriteSerialPort

+2

QThread的構造函數在調用線程中運行,而不是QThread實例所屬的線程。所以你必須在啓動你的工作線程後在其他地方啓動你的計時器。 –

+0

請在解答中更詳細地解釋您的評論和解決方案。 @KarstenKoop –

+0

評論是不正確的。 –

回答

3

你移動到另一個線程必須有它的父集的對象構造的每個對象:

class ReadWriteSerialPort : public QObject { 
    QSerialPort serialPort { this }; // important 
    QTimer timerSendVelocityPackets { this }; // etc. 
    ... 
}; 

您還必須確保有沒有直接調用來自其他線程的線程不安全方法ReadWriteSerialPort

此外,除非您正在輪詢數據,否則計時器驅動的數據包接收不正確。你應該根據串口發出的信號readyRead採取行動。

我還質疑單獨的閱讀器和書寫器:通常這些任務都需要知道目標設備的預期狀態,因此將它們分開可能是無益的。沒有看到更多的代碼很難說。

+0

串口也在worker類中聲明並初始化。雖然id​​on沒有串口的指針。如果你願意,我可以發佈整個代碼。 –

+0

@TheIndependentAquarius發佈重現問題的最小測試用例。我們不需要整個代碼。刪除不需要的每個語句以顯示問題,並將所有內容放入一個'main.cpp'文件中。我期望看到少於100行的代碼。 –

相關問題