2016-05-11 2 views
0

Deklarationsteil der Klasse Controller:Wie starte ich Timer aus der Arbeiter-Thread-Klasse in Qt?

class ProtocolPacket: public QQuickItem 
{ 
private: 

    Q_OBJECT 

    ... 
    QThread objWorkerThread; 

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

Der Konstruktor der Controller-Klasse:

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

Der Konstruktor der Worker-Thread-Klasse:

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

Ich bin receivi ng den Fehler:

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

Was mache ich falsch?

Ich wünsche den Timer von der Arbeiter-Klasse zu starten: ReadWriteSerialPort

+2

Der Konstruktor von QThread wird im aufrufenden Thread ausgeführt, nicht im Thread, zu dem die QThread-Instanz gehört. Sie müssen also Ihren Timer an anderer Stelle starten, nachdem Sie den Arbeitsthread gestartet haben. –

+0

Bitte erläutern Sie Ihren Kommentar näher und eine Lösung auch in einer Antwort. @KarstenKoop –

+0

Der Kommentar ist falsch. –

Antwort

3

Jedes Objekt in dem Objekt erstellt, das Sie auf einem anderen Thread verschieben müssen ihre Mutter Satz haben:

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

Sie müssen auch sicherstellen, dass Es gibt keine direkten Aufrufe in die Thread-unsicheren Methoden von ReadWriteSerialPort aus anderen Threads.

Darüber hinaus ist der Timer-gesteuerte Paketempfang falsch, wenn Sie nicht nach Daten suchen. Sie sollten auf das Signal readyRead reagieren, das von der seriellen Schnittstelle ausgegeben wird.

Ich frage auch den separaten Leser und Schreiber: Normalerweise müssen diese Aufgaben beide den erwarteten Zustand des Zielgeräts kennen, so dass die Trennung von ihnen nicht hilfreich sein kann. Es ist schwer zu sagen, ohne mehr Code zu sehen.

+0

Der serielle Port wird auch in der Worker-Klasse deklariert und initialisiert. Obwohl nicht Zeiger des seriellen Hafens haben. Ich kann den ganzen Code veröffentlichen, wenn Sie möchten. –

+0

@TheIndependentAquarius Veröffentlichen Sie einen Testmindestfall, der das Problem reproduziert. Wir brauchen nicht den gesamten Code. Entfernen Sie alle Anweisungen, die nicht benötigt werden, um das Problem anzuzeigen, und fügen Sie alles in eine einzige 'main.cpp' Datei ein. Ich erwarte weniger als 100 Zeilen Code. –