2015-10-21 98 views
0

我想通過Qt(Qt 5.4.0,Ubuntu 14.04.3)中的串行端口進行通信,並且爲了減少工作量,我希望將通信部分轉換爲第二個線程。因此,我創建下列文件:QObject:無法創建兒童

serial_controller.cpp:

#include "serial_controller.h" 

serial_controller_worker::serial_controller_worker(const QString &portname, int waitTimeout, int BaudRate) 
{ 
    this->portName = portname; 
    this->waitTimeout = waitTimeout; 
    this->baudrate = BaudRate; 
    this->serial.setPortName(this->portName); 
    this->serial.setBaudRate(this->baudrate); 
    if (!serial.open(QIODevice::ReadWrite)) 
    { 
     emit error(tr("Can't open %1, error code %2").arg(portName).arg(serial.error())); 
     qDebug() << tr("Can't open %1, error code %2").arg(portName).arg(serial.error()); 
     return; 
    } 
    else 
    { 
     emit error(tr("Opened %1").arg(portName)); 
     qDebug() << tr("Opened %1").arg(portName); 
    } 
} 

serial_controller_worker::~serial_controller_worker() 
{ 
    this->serial.close(); 
} 

void serial_controller_worker::process_data() 
{ 
    bool newData = false; 
    bool run = false; 
    this->mutex.lock(); 
    newData = this->sendNewData; 
    run = this->recvLoop; 
    this->mutex.unlock(); 
    if(run == false) 
    { 
     qDebug() << "Run is false, returning!"; 
     return; 
    } 
    else 
    { 
     if(newData == true) 
     { 
      qDebug() << "TransAction started!"; 
      QByteArray requestData = request.toLocal8Bit(); 
      qDebug() << "Writing data: " << requestData; 
      serial.write(requestData); 
      qDebug() << "Data written"; 
      if(serial.waitForBytesWritten(waitTimeout)) 
      { 
       if(serial.waitForReadyRead(waitTimeout)) 
       { 
        qDebug() << "Waiting for data!"; 
        QByteArray responseData = serial.readAll(); 
        while(serial.waitForReadyRead(10)) 
         responseData += serial.readAll(); 
        QString response(responseData); 
        QByteArray response_arr = response.toLocal8Bit(); 
        qDebug() << "Response is: " << response_arr.toHex(); 
        emit this->response(response); 
       } 
       else 
       { 
        qDebug() << "Wait read response timeout"; 
        emit this->timeout(tr("Wait read response timeout %1").arg(QTime::currentTime().toString())); 
       } 
      } 
      else 
      { 
       qDebug() << "Wait write request timeout!"; 
       emit this->timeout(tr("Wait write request timeout %1").arg(QTime::currentTime().toString())); 
      } 
      mutex.lock(); 
      this->sendNewData = false; 
      mutex.unlock(); 
     } 
     QThread::msleep(10); 
     this->process_data(); 
    } 

} 

void serial_controller_worker::transaction(const QString &request) 
{ 
     mutex.lock(); 
     this->sendNewData = true; 
     this->recvLoop = true; 
     this->request = request; 
     mutex.unlock(); 
     this->process_data(); 
} 


//Serial_controller functions 
serial_controller::serial_controller(const QString &portName, int waitTimeout, int BaudRate) 
{ 
    serial_controller_worker *newWorker = new serial_controller_worker(portName, waitTimeout, BaudRate); 
    newWorker->moveToThread(&workerThread); 
    connect(&workerThread, &QThread::finished, newWorker, &QObject::deleteLater); 
    connect(this, &serial_controller::newTransaction, newWorker, &serial_controller_worker::transaction); 
    connect(newWorker, &serial_controller_worker::response, this, &serial_controller::response_slot); 
    workerThread.start(); 
} 

serial_controller::~serial_controller() 
{ 
    workerThread.quit(); 
    workerThread.wait(); 
} 

void serial_controller::transaction(const QString &request) 
{ 
    emit this->newTransaction(request); 
} 



void serial_controller::response_slot(QString response) 
{ 
    emit this->response(response); 
} 

serial_controller.h:

#include <QObject> 
#include <QThread> 
#include <QVector> 
#include <memory> 
#include <QtSerialPort/QtSerialPort> 
class serial_controller_worker: public QObject 
{ 
    Q_OBJECT 
private: 
    QString portName; 
    QString request; 
    int waitTimeout; 
    QMutex mutex; 
    QWaitCondition cond; 
    int baudrate; 
    QSerialPort serial; 
    bool quit; 
    bool sendNewData = false; 
    bool recvLoop = false; 
public slots: 
    void transaction(const QString &request); 
signals: 
    void response(QString s); 
    void error(const QString &s); 
    void timeout(const QString &s); 
public: 
    serial_controller_worker(const QString &portname, int waitTimeout, int BaudRate); 
    ~serial_controller_worker(); 

    void process_data(void); 
}; 

class serial_controller: public QObject 
{ 
    Q_OBJECT 
private: 
    QThread workerThread; 
    QString portName; 
    QString request; 
    int waitTimeout; 
    QMutex mutex; 
    QWaitCondition cond; 
    int baudrate; 
    QSerialPort serial; 

public: 
    serial_controller(const QString &portName, int waitTimeout, int BaudRate); 
    ~serial_controller(); 

public slots: 
    void transaction(const QString &request); 
    void response_slot(QString response); 
signals: 
    void newTransaction(const QString &request); 
    void response(QString s); 
    void error(const QString &s); 
    void timeout(const QString &s); 
}; 

現在我有問題 一)致電serial_controller_worker::process_data()的時候,我得到的輸出

Writing data: "..." 
QObject: Cannot create children for a parent that is in a different thread. 
(Parent is QSerialPort(0x2533e60), parent's thread is QThread(0x2486850), current thread is QThread(0x25341e0) 
Data written 
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread 

然後我得到答案,但之後我無法再撥打serial_controller_worker::transaction(),我根本沒有注意到它被執行。爲什麼?我在這裏做錯了什麼?

編輯1:用於解決問題1是: 更換

QSerialPort serial; 

QSerialPort *serial; 
serial = new QSerialPort(this); 

儘管如此第二個問題是未解決的。

回答

0

好的,找到答案。
解決的第一個問題是:
我不得不更換

QSerialPort serial; 

QSerialPort *serial; 
serial = new QSerialPort(this); 

該溶液至第二個問題:
卸下線

this->process_data(); 

來自功能process_data()