单独的 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 中的串行端口的主要内容,如果未能解决你的问题,请参考以下文章