为什么 QSerialPort::writeData 使用单次定时器开始写入?

Why does QSerialPort::writeData start writes with a single-shot timer?

我正在尝试了解 Qt 的串口模块,但我不太熟悉 Qt 如何处理异步 I/O。在 Windows 上,QSerialPort::writeData 方法将要写入的数据放入环形缓冲区,然后在其 timeout 信号触发时启动单次 QTimer 以实际执行写入:

qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
{
    Q_Q(QSerialPort);
    writeBuffer.append(data, maxSize);
    if (!writeBuffer.isEmpty() && !writeStarted) {
        if (!startAsyncWriteTimer) {
            startAsyncWriteTimer = new QTimer(q);
            QObjectPrivate::connect(startAsyncWriteTimer, &QTimer::timeout, this, &QSerialPortPrivate::_q_startAsyncWrite);
            startAsyncWriteTimer->setSingleShot(true);
        }
        if (!startAsyncWriteTimer->isActive())
            startAsyncWriteTimer->start();
    }
    return maxSize;
}

readData方法不使用定时器,而是直接调用ReadFileEx

与仅调用 WriteFileEx 相比,单次计时器完成了什么?

间隔为 0 的 QTimer 有一个特殊情况:一旦控制 returns 到 event loop. The implementation on Unix/Linux does something similar,该计时器将触发,但不使用 QTimer,而是使用QSocketNotifier 的子类,当可以写入端口时将被调用。这两种实现都意味着您将缓冲数据并在返回主事件循环后将其写出。

我认为这样做有两个原因:

  • POSIX 和 Win32 串行 API 之间存在一些不同之处,需要以这种方式构建代码。据我所知,情况并非如此
  • @Mike 在评论中所说:这将允许在写入数据之前对其进行缓冲

缓冲似乎是最可能的原因,因为对您要写入的每条数据执行系统调用将是一项相当昂贵的操作。