为啥 QSerialPort::writeData 使用单次计时器开始写入?
Posted
技术标签:
【中文标题】为啥 QSerialPort::writeData 使用单次计时器开始写入?【英文标题】:Why does QSerialPort::writeData start writes with a single-shot timer?为什么 QSerialPort::writeData 使用单次计时器开始写入? 【发布时间】:2019-10-03 20:33:36 【问题描述】:我正在尝试了解 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
相比有什么作用?
【问题讨论】:
一个优点是这允许将多个连续的写入调用合并为一个对WriteFileEx
的调用(例如:port.write("a"); port.write("b"); port.write("c");
都转换为WriteFileEx("abc");
)。我不确定是否还有更重要的。
可能是为了实现异步处理。根据设备驱动程序的实现和要发送的数据的大小,有人可能认为直接调用 WriteFileEx 会是一个同步过程。或者可能是打算实现 WriteData 的超时错误检测过程只是一个错误。
【参考方案1】:
对于间隔为 0 的 QTimer
有一个特殊情况:一旦控制权返回到 event loop,此计时器将触发。 Unix/Linux 上的实现是 something similar,但不使用 QTimer,而是有一个 QSocketNotifier
的子类,当端口能够被写入时,它将被调用。这两种实现都意味着您将缓冲数据并在返回主事件循环后将其写出。
我能想到这样做有两个原因:
POSIX 和 Win32 串行 API 之间存在一些不同之处,需要以这种方式构造代码。据我所知,情况并非如此 @Mike 在评论中所说:这将允许数据在写入之前进行缓冲缓冲似乎是最可能的原因,因为对您要写入的每条数据进行系统调用将是一项相当昂贵的操作。
【讨论】:
以上是关于为啥 QSerialPort::writeData 使用单次计时器开始写入?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用 glTranslatef?为啥不直接更改渲染坐标?
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?