2016-05-11 2 views
0

Декларация часть класса контроллера:Как запустить таймеры из класса рабочей нити в Qt?

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

Последовательный порт также объявляется и инициализируется в рабочем классе. Хотя у Idon нет указателя на последовательный порт. Я могу опубликовать весь код, если вы хотите. –

+0

@ TheIndependentAquarius Опубликуйте минимальный тестовый пример, который воспроизводит проблему. Нам не нужен весь код. Удалите все утверждения, которые не нужны, чтобы показать проблему, и поместите все в один файл 'main.cpp'. Я ожидаю увидеть менее 100 строк кода. –