单独的 QThread 中的串行端口

Posted

技术标签:

【中文标题】单独的 QThread 中的串行端口【英文标题】:Serialport in a separate QThread 【发布时间】:2019-02-18 10:47:01 【问题描述】:

我想将串口插入一个单独的 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.

有人可以帮我解决崩溃吗?

非常感谢。

【问题讨论】:

也许题外话了,但是……你为什么觉得有必要创建一个新线程来管理QSerialPort 我没有时间解释这里犯的所有错误。这是一个简短的错误列表:全局变量(以奇怪的方式隐藏),对象拥有的线程被移动到线程,缺少实际读取的代码。事实上,我没有看到在这里使用线程的理由。我知道它们很漂亮,看起来像是解决所有性能问题的黄金解决方案,但是当你不知道自己在做什么时,它们很难掌握,甚至更难维护。 亲爱的@Marek,感谢您的回答。我需要将串口插入不同的线程以提高其性能,因为当我在用户界面上更改页面时,串口会暂时停止工作。我从没用过多线程,也不知道怎么做。 @MarekR 对不起,我写了一个不同的名字 【参考方案1】:

假设您的设备会响应文本,最好和最简单的方法是这样的:

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() 信号,就可以在不使用线程的情况下完成。

如果你仍然坚持使用线程,只需使用相同的对象树并将其移动到指定的线程。

【讨论】:

以上是关于单独的 QThread 中的串行端口的主要内容,如果未能解决你的问题,请参考以下文章

想将方法放入 QThread

带有 QThread 和线程模块的 Python 多线程

从 QThread 影响 QDialog

g_main_loop_run 阻塞 Qthread 并且不允许停止视频

Qthread 锁定 Gui PySide

QThread 移动到线程。 QThread 中的同步