Сериалпорт в отдельном QThread - PullRequest
0 голосов
/ 18 февраля 2019

Я хотел бы вставить последовательный порт в отдельный QThread, но приложение вылетает.Я написал следующие классы C ++

Worker.h

 class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void finished();
    void error(QString err);

public slots:
    void process();

};

class WorkerInterface : public QObject
{
    Q_OBJECT

public:
    explicit WorkerInterface(QObject *parent = nullptr);
    ~WorkerInterface();

    serialport *readSerialPort();

signals:
    void threadStoppedChanged();

public slots:
    void errorString(QString errorMsg);
    void stopThread();

private:
    QThread m_thread;
    serialPort *m_serial;
};

Worker::Worker(QObject *parent)
    : QObject(parent)
{
}

void Worker::process()
{

    emit finished();
}

Worker.cpp

WorkerInterface::WorkerInterface(QObject *parent)
    : QObject(parent)
    , m_thread(this)
{
    serialPort::serialPortMaster = new serialPort(nullptr);
    m_serial = serialPort::serialPortMaster;
    serialPort::serialPortMaster->moveToThread(&m_thread);
    connect(&m_thread, SIGNAL(started()),serialPort::serialPortMaster, SLOT(Init()));
    m_thread.start();

}

WorkerInterface::~WorkerInterface()
{
    m_thread.quit();
    m_thread.wait(1000);
    if (!m_thread.isFinished())
        m_thread.terminate();

}

void WorkerInterface::errorString(QString errorMsg)
{
    qDebug() << "error" << errorMsg;
}

void WorkerInterface::stopThread()
{
    m_thread.quit();
    m_thread.wait(1000);
    if (!m_thread.isFinished())
        m_thread.terminate();

    emit threadStoppedChanged();
}

serialPort* WorkerInterface::readSerialPort()
{
    return(m_serialPort);
}

В main.cpp я написал следующий код:

WorkerInterface workerInterface;
engine.rootContext()->setContextProperty("newserial", workerInterface.readSerialPort());

QQmlComponent component(&engine,QUrl(QStringLiteral("qrc:/Pages/Content/Qml/main.qml")));

QObject *qmlObject = component.create();

Когда код достигает последней инструкции в main.cpp, приложение вылетает, и в консоли создателя QT появляется следующеесообщения:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0xee18c0), parent's thread is QThread(0xc8d8b0), current thread is QThread(0x7fffffffdc60)

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0xee18c0), parent's thread is QThread(0xc8d8b0), current thread is QThread(0x7fffffffdc60)
QQmlEngine: Illegal attempt to connect to serialPort(0xee1710) that is in a different thread than the QML engine QQmlApplicationEngine(0x7fffffffdc30.

Может ли кто-нибудь помочь мне решить проблему?

Большое спасибо заранее.

1 Ответ

0 голосов
/ 19 февраля 2019

Предполагая, что у вас есть устройство, которое отвечает с текстом, лучший и самый простой способ сделать это что-то вроде этого:

class IODevLineReader
{
    Q_OBJECT
public:
    explicit IODevLineReader(QObject *parent);

public signals:
    void lineWasReceived(const QString &line);

public slots:
    void onReadyRead() {
        QIODevice *dev = qobject_cast<QIODevice *>(sender());
        while (dev && dev->canReadLine()) {
            auto lineBytes = dev->readLine();
            emit lineWasReceived(lineBytes);
        }
    }
};

Просто подключите QSerialPort::readyRead() к IODevLineReader::onReadyRead() и подключите некоторый слот к IODevLineReader::lineWasReceived() сигнал, и вы сделали без использования потоков.

И если вы все еще настаиваете на использовании потока, просто используйте то же дерево объектов и переместите его в указанный поток.

...