2

我以前使用过串行端口及其原始方法,如 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 毫秒

我现在的问题是:

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

1 回答 1

0

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

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

不幸的是,我还不知道如何回答您的第三个问题,所以我暂时将其打开。

于 2016-06-10T09:27:43.120 回答