c# - SerialPort.BaseStream.ReadAsync 缺少第一个字节

标签 c# asynchronous stream serial-port async-await

我正在尝试在 .net 中使用 SerialPort 类。

我选择让我的服务保持异步,所以我在 SerialPort.BaseStream 上使用异步方法。

在我的异步方法中,我将一个 byte[] 写入串行端口,然后开始读取,直到我在 n 毫秒内没有收到更多数据,然后返回该结果。

然而,问题是,除了打开串口后的第一个回复之外,我似乎错过了所有回复中的第一个字节。

如果我在每次响应(读取)后关闭端口,并在执行新请求(写入)之前再次打开它,第一个字节不会丢失。然而,这通常会导致 “访问端口 'COM4' 被拒绝。” 异常,如果我尝试在关闭后过早打开端口。似乎也没有必要为每次写入/读取打开/关闭。

这基本上就是我的方法:

private async Task<byte[]> SendRequestAsync(byte[] request)
{    
    // Write the request
    await _serialPort.BaseStream.WriteAsync(request, 0, request.Length);

    var buffer = new byte[BUFFER_SIZE];
    bool receiveComplete = false;
    var bytesRead = 0;

    // Read from the serial port
    do
    {
        var responseTask = _serialPort.BaseStream.ReadAsync(buffer, bytesRead, BUFFER_SIZE - bytesRead);
        if (await Task.WhenAny(responseTask, Task.Delay(300)) == responseTask)
        {
            bytesRead += responseTask.Result;
        }
        else
            receiveComplete = true;


    } while (!receiveComplete);

    var response = new byte[bytesRead];
    Array.Copy(buffer, 0, response, 0, bytesRead);

    return response;
}

我这样做有什么明显的错误吗?有没有更聪明的方法来异步实现相同的目标?

最佳答案

仅仅因为您没有观察到最后一个 ReadAsync() 并不意味着它被取消,它仍在运行,这显然通过它读取以下消息的第一个字节来体现。

您应该做的是使用 CancellationToken 取消最后一个 ReadAsync()。请注意,超时和读取之间可能存在竞争,但我假设如果超时已过,则读取不可能在没有另一次写入的情况下完成。

代码看起来像这样:

var cts = new CancellationTokenSource();

do
{
    var responseTask = _serialPort.BaseStream.ReadAsync(
        buffer, bytesRead, BUFFER_SIZE - bytesRead, cts.Token);

    if (await Task.WhenAny(responseTask, Task.Delay(300)) == responseTask)
    {
        bytesRead += responseTask.Result;
    }
    else
    {
        cts.Cancel();
        receiveComplete = true;
    }
} while (!receiveComplete);

请注意,原因和解决方案都是我的猜测,当然有可能我对其中一个或两个都错了。

关于c# - SerialPort.BaseStream.ReadAsync 缺少第一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35870794/

相关文章:

c# - WPF-防止在鼠标单击时激活窗口

c# - 为什么 C# 锁不应该用于长时间操作?

我在做什么的 Python 多处理进程或池?

python - Tornado asynchttpclient 结果为 None

c# - 在静态方法中管理一次性对象

c# - 从 View 组件渲染原始 html

c# - 如何强制 Visual Studio *真的*停止执行?

c# - 如何在 OfType() 之后使用 Include()?

c++ - 从 istream 读取自定义坐标类

java - 内存映射输出流生成带有尾随零的输出文件