简体   繁体   English

如何在其他类的嵌套循环内进入主事件循环QCoreApplication来实现网络操作?

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

This post is similar to the first one I posted, but I made some changes and I understand what is wrong. 这篇文章与我发布的第一篇文章相似,但是我进行了一些更改,并且我知道出了什么问题。 The error lies in event loop QCoreApplication that is not called within the nested loops and consequently the networking events are not met. 错误在于嵌套循环中未调用的事件循环QCoreApplication,因此未满足联网事件。 My problem is always to send a json to my API Rest. 我的问题总是向我的API Rest发送一个json。 This is the tour that is my code: the main class that calls the SerialReader laws of bytes from the serial port, identifies if the package is right and if it sends the Parser class that divides the various bytes and then sending those required API 这是我的代码之旅:从串行端口调用SerialReader字节定律的主类,确定包是否正确,是否发送将各个字节分开的Parser类,然后发送所需的API

This is my main.cpp 这是我的main.cpp

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

This is my serialreader.cpp / serialreader.h 这是我的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);
            ...
        }
    }
 }

This is my parser.cpp / parser.h 这是我的parser.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);
}

In practice after entering the serial reader read in continuation of bytes so as to become an infinite loop and are therefore always recalled all nested methods. 实际上,进入串行读取器后,将连续读取字节,以使其成为无限循环,因此始终调用所有嵌套方法。 I tried to solve the problem with the static method QCoreApplication::processEvents(QEventLoop::AllEvents) but I can not play the main loop QCoreApplication. 我尝试使用静态方法QCoreApplication::processEvents(QEventLoop::AllEvents)解决问题,但无法播放主循环QCoreApplication。 How can I do? 我能怎么做?

Calling QCoreApplication::processEvents does not seem to be a good solution and with little refactoring you won't need it. 调用QCoreApplication :: processEvents似乎不是一个好的解决方案,只需很少的重构,您将不需要它。 Qt gives you two options to handle serial port. Qt提供了两种选择来处理串行端口。 You can use either blocking API or async API of QSerialPort . 您可以使用QSerialPort的阻塞API或异步API。 However when using blocking API (as you are doing when calling waitForReadyRead() ) you should move code that reads serial data to some worker thread to not block the main event loop. 但是,在使用阻塞API时 (就像在调用waitForReadyRead()时所做的那样 ),您应该将读取串行数据的代码移动到某个工作线程中,以不阻塞主事件循环。 The other option is to use async API and connect to readyRead() signal to process incoming data. 另一个选择是使用异步API并连接到readyRead()信号来处理传入的数据。

In your case it is probably easier to do modify SerialReader class and replace while(...) loop with asynchronous processing of incoming data in a slot connected to readyRead() signal. 在您的情况下,修改SerialReader类并用连接到readyRead()信号的插槽中异步处理传入数据来替换while(...)循环可能更容易。

There are good examples for QSerialPort http://doc.qt.io/qt-5/qtserialport-examples.html QSerialPort有很好的示例http://doc.qt.io/qt-5/qtserialport-examples.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM