QObject:无法创建子项

时间:2015-10-21 08:28:18

标签: c++ qt serial-port

我想通过Qt(Qt 5.4.0,Ubuntu 14.04.3)中的串口进行通信,为了减少工作量,我希望将通信部分转换为第二个线程。因此我创建了以下文件:

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

现在我遇到了问题 a)在调用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);

还是第二个问题尚未解决。

1 个答案:

答案 0 :(得分:0)

好的,找到了答案 第一个问题的解决方案是:
我必须替换

QSerialPort serial;

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

第二个问题的解决方案:
删除行

this->process_data();

来自函数process_data()