【问题标题】:Proper way using timeouts with serial port and ReadAsync使用串行端口和 ReadAsync 超时的正确方法
【发布时间】:2016-10-11 04:25:45
【问题描述】:

我以前使用过串行端口及其原始方法,例如 BytesToRead、Read 和 Write。据说这些是不可靠的,我有很多忙等待我试图切换到它的异步方法。

我需要从具有 2 个不同超时的串行端口读取。第一次超时在两条消息之间(此处为 2000 毫秒),第二次超时在 2 个字符之间(此处为 10 毫秒)。因此,我为每个 ReadAsync 调用更改 ReadTimeout,如下所示:

    public int Read(byte[] buffer, int offset, int count, bool isFirstChar)
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();

        try
        {
            m_serialPort.ReadTimeout = isFirstChar ? 2000 : 10;
            Task<int> task = m_serialPort.BaseStream.ReadAsync(buffer, offset, count);
            task.Wait();
            return task.Result;
        } catch (AggregateException err)
        {
            stopWatch.Stop();
            int cnt = 0;
            foreach (Exception e in err.InnerExceptions)
            {
                if (e is TimeoutException)
                {
                    Console.WriteLine(string.Format("Exception {0}: {1} Timeout: {2} ms", ++cnt, e.Message, stopWatch.ElapsedMilliseconds));
                }
            }

            return -1;
        }
    }

发生 AggregateException 且未接收到字节时的输出:

异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:3584 毫秒
异常 1:操作已超时。超时:2014 毫秒
异常 1:操作已超时。超时:2017 毫秒
异常 1:操作已超时。超时:2012 毫秒
异常 1:操作已超时。超时:2011 毫秒
异常 1:操作已超时。超时:2016 毫秒
异常 1:操作已超时。超时:2012 毫秒
异常 1:操作已超时。超时:2011 毫秒
异常 1:操作已超时。超时:2013 毫秒
异常 1:操作已超时。超时:2013 毫秒

我现在的问题是:

  • 这是使用带有 .Wait() 的 ReadAsync 方法的正确方法吗?
  • 可以在每次调用 ReadAsync 之前更改 ReadTimeout 吗?
  • 我应该使用 CancellationToken 作为 ReadAsync 中的参数吗?如果是,最好的方法是什么?

【问题讨论】:

  • 这是哪个 .NET 版本?因为我在 MSDN 上找不到 SerialPort.BaseStream.ReadAsync(),也没有提供智能感知这个作为我的选项
  • 我使用的是 4.5!看看这里:link
  • 我还是一头雾水,BaseStream 属于Stream 类型,ReadAsynch 方法属于StreamReader。我无法重现您的代码。
  • 不,这是不正确的。 only 使用异常来处理异常情况。您的输出表明超时是完全正常的。而且您的代码也不会将其视为异常。所以根本不要使用超时。
  • 不,超时是不正常的,因为它通常不会发生。在我的示例(输出)连接丢失....我还必须使用超时来确定消息是否有效。

标签: c# asynchronous mono serial-port rs485


【解决方案1】:

问题1:你以同步的方式使用异步方法。 通常你会给它一个回调函数等待,直到一个事件被触发并且这个函数可以被执行。 以下是异步等待方法的示例 12

问题 2:如果您的情况需要您这样做。我不明白为什么不。

很遗憾,我还不知道如何回答您的第三个问题,所以我暂时不回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多