【问题标题】:Unable to use SerialDevice.ReadTimeout in Windows 10 IoT无法在 Windows 10 IoT 中使用 SerialDevice.ReadTimeout
【发布时间】:2015-08-22 15:43:15
【问题描述】:

我正在尝试在 Raspberry Pi 2 上的 Windows 10 IoT 上实现 ModBus 主控。 我正在使用外部 USB 转 RS-232 适配器,因为内部串行端口是为内核调试保留的。

串行端口正在工作。我的问题主要是关于阅读时的超时。

这是我的代码:

// Initialization
serialDevice.ReadTimeout = new TimeSpan(0, 0, 0, allowedTimeBetweenBytes);
serialDataReader.InputStreamOptions = InputStreamOptions.Partial;

// Reading
uint bytesRead = await serialDataReader.LoadAsync(MaxBufferSize); // 256
// Now use ReadBytes to get actual bytes

由于串行端口 RX 输入上没有可用的字节,我希望 LoadAsync 方法在等待后返回 0。不幸的是,它永远不会回来。 (好吧,它确实在收到 256 个字节后返回,但这不是我想要的)

由于 ModBus 大量使用超时,我不知道如何实现它。我什至不确定我能做到...

是否有人已经在 Windows 10 IoT 串行端口上使用了超时功能?

【问题讨论】:

  • 好吧,显然 InputStreamOptions.Partial 不起作用。所以掷骰子,然后尝试 InputStreamOptions.ReadAhead 和 None。

标签: c# serial-port timeout windows-10-iot-core


【解决方案1】:

是的,我也无法正常工作。我不确定ReadTimeout 内部实际使用SerialDevice 类的位置。但我最终通过将超时复制到CancellationTokenSource 来得到一些工作。

您可以在以下示例中看到它的使用情况,我为旧系列 Mettler Toledo PS 60 运输秤编写,其中deviceSerialDevice 的一个实例。至少在我的情况下似乎有效。

using (var writer = new DataWriter(device.OutputStream))
{
    writer.WriteString("W\r\n");

    using (var cts = new CancellationTokenSource(device.WriteTimeout))
    {
        await writer.StoreAsync().AsTask(cts.Token);
    }

    writer.DetachStream();
}

using (var reader = new DataReader(device.InputStream))
{
    using (var cts = new CancellationTokenSource(device.ReadTimeout))
    {
        var read = await reader.LoadAsync(12).AsTask(cts.Token);

        if (read >= 12)
        {
            var data = reader.ReadString(12);
            reader.DetachStream();

            return ExtractWeightChangedEventArgs(data);
        }
    }
}

【讨论】:

  • 谢谢尼古拉斯。我使用了类似的代码,它对我也很好!至少我们现在有了一种超时读取字节的方法。
【解决方案2】:

刚刚花了几个星期来解决这个问题并进行测试。

  1. ReadTimeout 对读取调用的第一个字节没有影响。读取调用总是永远等待第一个字节。

  2. ReadTimeout = 0ms 会导致读取调用永远等待多字节读取调用中请求的所有后续字节。

  3. ReadTimeout = 大于 0 毫秒会导致读取调用在该时间之后等待第一个之后的任何后续字节时超时。

  4. ReadTimeout 是一个 TimeSpan,这意味着调用者可以指定一个分辨率超过毫秒的超时值。但是,底层的 Windows 调用只有毫秒级的分辨率。

  5. 我使用具有超时值的 CancellationTokenSource 的实验似乎导致 SerialDevice 对象在超时取消后变得不稳定。

我最终创建了一个从 SerialDevice 派生的类。派生类启动一个后台任务,该任务简单地向基本 SerialDevice 类发出读取请求,并将返回的数据存储在队列中。我将 ReadTimeout 设置为 1 毫秒,以便我的后台任务可以发出大量读取请求,然后在数据可用时接收数据并将其存储到队列中,而无需等待整个请求。

我创建了一个循环队列以提高内存效率。 .NET 不提供一种标准。在处理高波特率时,将读取数据复制到队列需要非常高效。意思是复制数据块。不要一个字节一个字节地处理数据。

派生类提供了备用读取方法,这些方法将从队列中返回数据,并且如果队列中没有数据,则可以立即返回。

由于 SerialDevice 读取发生在后台任务中,因此无需取消读取请求并冒着破坏 SerialDevice 的风险。当派生类正在关闭 SerialDevice 并进行处置时,当后台任务被发出终止信号时,读取只有一个 CancellationToken。

【讨论】:

    猜你喜欢
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多