Qt5 多线程:信号仅以一种方式工作
Posted
技术标签:
【中文标题】Qt5 多线程:信号仅以一种方式工作【英文标题】:Qt5 multi-threading: signals work in one-way only 【发布时间】:2017-08-07 18:47:28 【问题描述】:这里:Qt multi-thread with GUI 我已经学习了如何创建后台工作程序(Engine
类)。
在那个类中,我有一个QSerialPort
对象,在主线程中运行(请参阅How to setup QSerialPort on a separate thread?)。
我正在使用信号/槽机制来发送/接收数据。但它只能以一种方式工作。 Engine
对象(“工作线程”)发出的信号由QSerialPort
(“主线程”)接收。反之亦然:QSerialPort
发出的任何信号都不会被Engine
接收。
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QTimer>
#include "myserial.h"
class Engine : public QObject
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
QTimer m_timer;
MySerial m_serial;
signals:
void serialSendMessage(QByteArray data);
private slots:
void lineReceived(QByteArray line);
void foo();
public slots:
void run();
void open(QString port, quint32 baudrate);
void close();
;
#endif // ENGINE_H
engine.c
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
connect(&m_timer, &QTimer::timeout, this, &Engine::foo);
m_timer.setInterval(200);
// THIS IS NEVER EXECUTED!
void Engine::lineReceived(QByteArray line)
qDebug() << line;
// THIS IS RECEIVED BY QSERIALPORT
void Engine::foo()
emit serialSendMessage("Hello World!");
void Engine::run()
// THIS DOESN'T WORK!
connect(&m_serial, &MySerial::lineReceived, this, &Engine::lineReceived);
// THIS WORK!
connect(this, &Engine::serialSendMessage, &m_serial, &MySerial::sendMessage);
void Engine::open(QString port, quint32 baudrate)
m_serial.open(port, baudrate);
QTimer::singleShot(0, &m_timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
void Engine::close()
m_serial.close();
MySerial.h
#ifndef MYSERIAL_H
#define MYSERIAL_H
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
class MySerial : public QSerialPort
Q_OBJECT
public:
explicit MySerial(QObject *parent = 0);
bool open(QString port, quint32 baudrate);
using QSerialPort::open;
QByteArray sendMessage(QByteArray data, bool nmea);
signals:
void lineReceived(QByteArray line);
private slots:
void onReadyRead();
;
#endif // MYSERIAL_H
MySerial.c
#include "myserial.h"
#include <QDebug>
MySerial::MySerial(QObject *parent) : QSerialPort(parent)
bool MySerial::open(QString port, quint32 baudrate)
disconnect(this, 0, 0, 0);
connect(this, &FemtoSerial::readyRead, this, &MySerial::onReadyRead);
setPortName(port);
if (!open(QIODevice::ReadWrite)) return false;
setDataBits(QSerialPort::Data8);
setParity(QSerialPort::NoParity);
setStopBits(QSerialPort::OneStop);
setBaudRate(baudrate);
setFlowControl(QSerialPort::NoFlowControl);
return true;
void MySerial::onReadyRead()
static QList<QByteArray> lines;
static QByteArray buffer;
buffer += readAll();
int index = buffer.indexOf("\r");
while (index != -1)
lines.append(buffer.left(index + 1));
buffer = buffer.mid(index + 1);
index = buffer.indexOf("\r");
// THIS SIGNAL IS EMITTED!
while (!lines.isEmpty()) emit lineReceived(lines.takeFirst());
QByteArray MySerial::sendMessage(QByteArray data)
write(data);
return data;
编辑
尝试添加QEventLoop
:
void Engine::run()
QEventLoop loop;
connect(&m_serial, &MySerial::lineReceived, this, &Engine::lineReceived);
connect(this, &Engine::serialSendMessage, &m_serial, &MySerial::sendMessage);
loop.exec();
行为相同:发送数据,但从不执行接收槽。
【问题讨论】:
void Engine::run()
连接几个信号并立即结束其线程。正如我们在上一个问题中告诉您的那样,它应该具有事件循环。
抱歉,我没有完全理解您的 cmets。我正在重新阅读它们和相关链接。
我放弃了,我不明白我在哪里以及为什么需要QEventLoop
。我将整个Engine
移动到另一个线程中,我没有将QThread
子类化(我试图捕捉finished
信号并且它不会触发)。此外,发射的信号起作用。无论如何,在run()
函数中添加QEventLoop
不会改变行为。你介意澄清一下发生了什么吗?
当 void Engine::run()
完成其工作时,Engine
线程完成。调用它的基类。 QThread::run()
在退出之前进行事件循环。
@Mark,尽量不要使用额外的线程。使用所有可用的信号和插槽,在条件成立之前永远不要阻塞线程。这会让事情变得更清楚。
【参考方案1】:
bool MySerial::open(QString port, quint32 baudrate)
//<s>disconnect(this, 0, 0, 0);</s> // <--- strikeout
connect(this, &FemtoSerial::readyRead, this, &MySerial::onReadyRead);
// ...
来自文档:
断开连接到对象信号的所有东西
断开连接(myObject, 0, 0, 0);
这意味着来自myObject
的信号,而不是相反。
该行阻止Engine
中的槽被执行,因为它刚刚与源信号断开连接。
Engine
可能会在端口关闭时断开连接,以避免下次打开时出现多个连接。
【讨论】:
以上是关于Qt5 多线程:信号仅以一种方式工作的主要内容,如果未能解决你的问题,请参考以下文章
Mudblazor DatePicker 绑定仅以一种方式工作
C++学习笔记:高级编程:模板,预处理器,信号处理,多线程,Web编程