【问题标题】:How to flush the input buffer of a SerialDevice如何刷新 SerialDevice 的输入缓冲区
【发布时间】:2016-07-08 13:32:01
【问题描述】:

我正在创建一个 UWP 应用程序,该应用程序需要通过它公开的虚拟串行端口从 USB 输入设备读取数据。

我使用this tutorial 来实现使用SerialCommunication.SerialDevice 类的工作原型。但是,我需要在第一次打开串行端口时刷新输入流,以便在应用程序连接到输入设备之前丢弃输入设备缓冲区中可能存在的任何不需要的数据。

显而易见的解决方案似乎是继续读取端口,直到没有任何内容可供读取;像这样:

uint bytes;

do
{
    bytes = await _dataReader.LoadAsync(ReadBufferLength);
    _dataReader.ReadString(bytes);
} while (bytes > 0);

但是,这不起作用,因为如果没有要读取的数据,LoadAsync() 会无限期地等待。

有没有办法在尝试读取之前查询输入流的内容,或者无条件刷新它?

感谢您的建议,

提姆

更新:为了响应@Hans Passant 的 cmets,我将代码修改如下,以便在尝试读取输入缓冲区之前检测它:

await Task.Delay(1000);
Debug.WriteLine("BytesReceived: {0}", _serialDevice.BytesReceived); // 0 bytes
var bytesRead = await _dataReader.LoadAsync(ReadBufferLength);
Debug.WriteLine("BytesRead: {0}", bytesRead); // 75 bytes

因此,尽管等待了 1000 毫秒(让设备有足够的时间发送缓冲区中的内容),BytesReceived 未能检测到任何数据,但LoadAsync 之后立即读取了 75 个字节。

【问题讨论】:

  • 使用 SerialDevice.BytesReceived 属性了解您可以读取多少字节而不阻塞。
  • @Hans 谢谢 - 很好的建议 - 但这似乎不起作用。如果我阅读 SerialDevice.BytesReceived 它总是返回零,即使对 _dataReader.LoadAsync 的立即后续调用返回一个正值。
  • 当 BytesReceived 为 0 时,您为什么要尝试清除,这对我来说并不清晰。最合乎逻辑的解释是,当设备看到握手信号打开时,它会立即发送一些东西。但这需要时间,在 9600 波特下至少需要一毫秒。如果你也想摆脱这些,那么你必须 Task.Delay() 100 毫秒,给予或接受。
  • @Hans:是的,我的想法完全一样,所以我在发布最后一条评论之前测试了延迟。我已经更新了我的问题,以准确显示我测试的内容及其产生的结果。

标签: serial-port buffer uwp flush


【解决方案1】:

DataReader.LoadAsync() 在收到一个或多个字节之前不会返回。如果您的输入缓冲区为空,它将阻塞您的代码。

您可以使用 CancellationToken 取消读取任务,以“刷新”串行输入缓冲区。

下面是实现这一目的的代码。

using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1000)))
{
     await dataReaderObject.LoadAsync(1024).AsTask(cts.Token);
}

【讨论】:

  • 谢谢,这是解决问题的明智之举。
猜你喜欢
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2010-12-25
  • 2020-10-05
  • 2010-09-20
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多