如何在其他类的嵌套循环中获得主事件循环QCoreApplication,以实现网络操作

How to get to the main event loop QCoreApplication within nested loops of other classes for implementing networking operations?

本文关键字:QCoreApplication 循环 事件 操作 网络 实现 其他 嵌套循环      更新时间:2023-10-16

这篇文章类似于我发布的第一个,但我做了一些改变,我知道什么是错的。错误位于事件循环QCoreApplication中,该循环未在嵌套循环中调用,因此无法满足网络事件。我的问题总是发送json到我的API Rest。这是我的代码:主类从串行端口调用SerialReader的字节定律,确定包是否正确,如果它发送解析器类划分各种字节,然后发送那些所需的API

这是我的main.cpp
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SerialReader serialReader;
    QTimer::singleShot(0, &serialReader, SLOT(runSerialReader()));
    ...
    return a.exec();
}

这是我的serialreader.cpp/serialreader.h

/*serialreader.h*/
class SerialReader : public QObject
{
    Q_OBJECT
...
public:
    void processData(QByteArray datas);
public slots:
    void runSerialReader();
private:
    Parser parser;
...
};
/*serialreader.cpp*/
SerialReader::SerialReader() {}
void SerialReader::runSerialReader(){
    ...
    if (serialPort->isOpen())
    {
        qDebug() << "Serial port is open...";
        while (serialPort->waitForReadyRead(50))
        {
            QByteArray datas = serialPort->readAll();
            if (datas.size() == 0){
                qDebug() << "ERROR data not read";
            } else {
                processData(datas);
            }
        }
    } else {
        qDebug() << "OPEN ERROR: " << serialPort->errorString();
    }
    serialPort->close();
    qDebug() << "...serial port is closed!";
    ...
}
void SerialReader::processData(QByteArray datas)
{
    for (int i = 0; i < datas.size(); i++)
    {
        switch (state)
        {
        ...
        case EXIT:
            ...
            parser.setPackage(serialBuffer);
            ...
        }
    }
 }

这是我的解析器。cpp/parser.h

/*parser.h*/
class Parser : public QObject
{
    Q_OBJECT
public:
    ...
    QQueue<QByteArray> queue;
    void setPackage(QByteArray &serialBuffer);
    void sendPacketToAPI(QByteArray &bufferToPacket);
public slots:
   void replyFinished(QNetworkReply *reply);
private:
    QNetworkAccessManager *m_manager;
    quint8 m_a;
    quint8 m_b;
}
/*parser.cpp*/
Parser::Parser()
    : m_manager { new QNetworkAccessManager }
{
    connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}
void Parser::setPackage(QByteArray &serialBuffer){
    ...
    bufferToPacket.append(bufferToParse.at(i));
    ...
}
void Parser::replyFinished(QNetworkReply *reply)
{
    reply->deleteLater();
    qDebug() << "~error " << reply->errorString();
    qDebug() << "reply delete!";
    qDebug() << "https post_request done!";
}
void Parser::sendPacketToAPI(QByteArray &bufferToPacket){
    m_a = bufferToPacket.at(0);
    m_b = bufferToPacket.at(1);
    QNetworkRequest request;
    request.setUrl(QUrl ("http://..."));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    QString json = QString("{"a":"%1","b":"%2"}").arg(m_a).arg(m_b);
    m_manager->post(request, json.toUtf8()); 
    QCoreApplication :: processEvents (QEventLoop :: AllEvents);
}

在实际操作中,在进入串行读卡器后连续读取字节,从而形成一个无限循环,因此总是会召回所有嵌套的方法。我试图用静态方法QCoreApplication::processEvents(QEventLoop::AllEvents)解决问题,但我无法播放主循环QCoreApplication。我该怎么办?

调用QCoreApplication::processEvents似乎不是一个好的解决方案,并且您不需要进行少量重构。Qt提供了两个选项来处理串行端口。您可以使用QSerialPort的阻塞API或异步API。然而,当使用阻塞API时(正如您在调用waitForReadyRead()时所做的那样),您应该将读取串行数据的代码移动到一些工作线程中,以避免阻塞主事件循环。另一个选择是使用async API并连接到readyRead()信号来处理传入的数据。

在您的情况下,可能更容易做的是修改SerialReader类,并将while(…)循环替换为连接到readyRead()信号的插槽中的传入数据的异步处理。

QSerialPort有很好的例子http://doc.qt.io/qt-5/qtserialport-examples.html

相关文章:
  • 没有找到相关文章