QSerialPort的readLine()与readAll()相比速度极慢

8

我正在使用QtSerialPort / QSerialPort从串口读取数据,该数据以换行符'\n'和回车符'\r'分隔,这是我用于解析的方式。每行的长度可能会有所不同,但从每行的格式中提取数据非常容易。

//signal/slot connection on readyRead() is as follows:
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));

其中readData()的定义如下:

void MainWindow::readData()
{
   //As mentioned below, which I will reiterate, I have already tried the addition of 
   // canReadLine():
   if (serial->canReadLine()){
     QByteArray data = serial->readLine();
     //QByteArray allData = serial->readAll();
     parseSerialBytes(data);
     //console->putData(data);
     //console->putData(alldata);
   }
}

然而,函数QIODevice::readLine()的速度非常慢,相对于QIODevice::readAll()来说明显阻止了数据以满频率接收。
有人可以解释一下如何正确使用readLine()函数,这样我就不必通过循环readAll()QByteArray来解析每一行。我使用了“终端”Qt小部件示例来创建这个异步串口读取功能。
谢谢事先提供帮助 - 这似乎是一个普遍的问题,我还没有在这里找到答案。

1
作为评论,我想补充一下,我已经用 if (serial->canReadLine()) 包含了我的 serial->readLine() 语句,但数据读取频率似乎没有明显改变。我还注意到这几乎与一个 VB 在 Visual Studio 用户提出的问题完全相同 像这个,以及其他使用其他 IDE 和语言的人也提出了这个问题,但都没有解决。非常奇怪。 - Rachael
还要注意,许多Qt示例代码并没有展示如何构建和设计大型应用程序,就像我的大多数示例一样(没人有时间去阅读它)。Qt示例通常是为了演示一组有限的功能而存在的手段。不可否认,其中许多已经过时且不太好。 - Kuba hasn't forgotten Monica
1个回答

7
这是一个常见的错误。每一块数据只会调用一次readData,而不一定是每一行都调用。
只要有数据可读,就需要继续读取行。在小部件类中进行串口读取也是不好的设计。应该将其移动到单独的对象中。
class Receiver : public QObject {
  Q_OBJECT
  QSerialPort m_port;
  QByteArray m_buffer;
  void processLine(const QByteArray & line) {
    ...
  }
  Q_SLOT void readData() {
    // IMPORTANT: That's a *while*, not an *if*!
    while (m_port.canReadLine()) processLine(m_port.readLine());
  }
public:
  Receiver(QObject * receiver = 0) : QObject(parent) {
    connect(&m_port, &QIODevice::readyRead, this, &Receiver::readData);
    ...
  }
}

你的错误在于如下实现了readData。这样的代码只读取一行,无论有多少行可供读取。由于每次调用时都会留下越来越多的累积数据未读取,因此它会显得“慢”。最终它会耗尽堆内存。

void readData() {
  // WRONG!
  if (m_port.canReadLine()) processLine(m_port.readLine());
}

啊!谢谢!!我简直不敢相信自己没发现我用了“if”。感谢你写的所有代码。我一开始没明白你上面的评论(while != if)是什么意思。现在我很生自己的气,但无论如何,这似乎是我看到的一个常见的用法错误,所以我的错误现在可能会帮助别人。真的非常感谢你的帮助。 - Rachael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接