Qt-invokeMethod+QEvent实现同步访问QIODevice
1.子类封装
头文件
#include <QObject> #include <QTcpSocket> #include <QThread> class Device01 : public QObject { Q_OBJECT public: explicit DeviceS01(QObject *parent = nullptr); public slots: void connet(const QString& ip, int port);void setFreq(const QString& scpi); QString getTemp(int timeout); private slots: void on_stateChanged(QTcpSocket::SocketState state); //状态变更 signals: void sig_timeOutQuery(); private: std::atomic_bool m_inited = { false }; std::shared_ptr<QTcpSocket> m_tcpSocket = nullptr; //socket对象 };
注意:需要定义成槽函数
源文件
void Device01::connet(const QString &ip, int port) { qDebug()<<"connet"; do { if (m_inited) { break; } m_tcpSocket = std::make_shared<QTcpSocket>(this); //socket初始化 QObject::connect(m_tcpSocket.get(), &QTcpSocket::stateChanged, this, &Device01::on_stateChanged);//socket状态变更 m_tcpSocket->connectToHost(ip, port); }while(0); } void Device01::setFreq(const QString &freq) { if (!m_inited) { return; } QString scpi = "FREQ "+freq; m_tcpSocket->write(scpi.toLatin1()); } QString Device01::getTemp(int timeout) { qDebug() << "getTemp:" << QThread::currentThreadId(); QString ret = ""; //[1] 状态判断 if (!m_inited) { return ret; } //[2] 写指令 QString scpi = "TEMP?"; m_tcpSocket->write(scpi.toLatin1()); //[2] 查询结果 QEventLoop loop; // 创建事件循环 QObject::connect(this, &Device01::sig_timeOutQuery, &loop, &QEventLoop::quit); QTimer::singleShot(timeout, this, [&](){ emit sig_timeOutQuery(); }); auto async = QObject::connect(m_tcpSocket.get(), &QTcpSocket::readyRead, this, [&](){ auto rsp = m_tcpSocket->readAll(); ret = rsp; emit sig_timeOutQuery(); }); loop.exec(); // 进入事件循环,等待服务器响应 QObject::disconnect(async); return ret; } void Device01::on_stateChanged(QAbstractSocket::SocketState state) { qDebug()<<"state"<<state; //[1] 正在连接状态 if (QAbstractSocket::ConnectingState == state) { m_inited = false; } //[2] 连接成功状态 else if (QAbstractSocket::ConnectedState == state) { m_inited = true; } //[3] 已断开状态 else if (QAbstractSocket::UnconnectedState == state) { m_inited = false; } }
2.初始化
m_deviceThread = std::make_shared<QThread>(); //线程对象 m_device01 = std::make_shared<Device01>(); //01设备 m_device01->moveToThread(m_deviceThread.get()); m_deviceThread->start();
3.使用
QMetaObject::invokeMethod(m_device01.get(), "setFreq", Qt::QueuedConnection, Q_ARG(QString, "100")); QString temp; QMetaObject::invokeMethod(m_device01.get(), "getTemp", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, temp), Q_ARG(int, 3000));
注意没有返回值和引用参数的用QueuedConnection;
有返回值或者参数是引用用BlockingQueuedConnection,会保证invoke的地方会等槽函数执行完成再往下走;
两者调用的槽函数都在子线程中运行
长风破浪会有时,直挂云帆济沧海!
可通过下方链接找到博主
https://www.cnblogs.com/judes/p/10875138.html