【发布时间】: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