【发布时间】:2018-11-16 10:17:21
【问题描述】:
您好,我在串口上有一个简单的通信,一切都根据书和文档,所以开放端口方法如下所示:
public SerialPort OpenPort(string portName)
{
Port = new SerialPort(portName, BaudRate);
try
{
Port.Open();
Port.DtrEnable = true;
Port.RtsEnable = true;
Port.DataReceived += DataReceivedEvent;
}
catch (Exception e)
{
Console.WriteLine($"ERRROR: {e.Message}");
}
return Port;
}
这里我们有一个关于数据读取的事件:
private async void DataReceivedEvent(object sender, SerialDataReceivedEventArgs e)
{
var data = new byte[Port.BytesToRead];
await Port.BaseStream.ReadAsync(data, 0, data.Length);
Response = data;
isFinished = true;
}
一切都很好,花花公子,但现在我想按需发送消息并将响应存储在属性中,我还想在该任务超时时添加取消令牌。所以我想出了这个方法:
public async Task SendMessenge(byte[] messange)
{
var cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
cancellationTokenSource.CancelAfter(5000);
token.ThrowIfCancellationRequested();
isFinished = false;
try
{
Task worker = Task.Run(() =>
{
while (!isFinished)
{
}
}, token);
await Port.BaseStream.WriteAsync(messange, 0, messange.Length, token);
await worker;
}
catch (OperationCanceledException e)
{
throw new OperationCanceledException(e.Message, e, token);
}
}
问题在于这个while循环,如果它是任务,它会进入无限循环,并且它不会捕获超时令牌,如果我将它放在任务之外并删除工作人员它可以工作,但我会丢失取消令牌。我想我可以做一些手动倒计时,比如:
double WaitTimeout = Timeout + DateAndTime.Now.TimeOfDay.TotalMilliseconds;
while (!(DateAndTime.Now.TimeOfDay.TotalMilliseconds >= WaitTimeout)|| !isFalse)
但它看起来很丑。
所以我认为我的基本问题是如何有效地等待事件响应并获得超时?
【问题讨论】:
-
while (!isFinished) { }ManualEventResetSlim ...更多的是Wait(timeout)... -
异常处理是我最讨厌的事情,而你的处理并不理想。对于初学者,您将在发生致命异常后继续操作,并且没有正确记录/公开内容。这里有两篇关于我经常链接的材料的文章:blogs.msdn.microsoft.com/ericlippert/2008/09/10/… | codeproject.com/Articles/9538/…
-
将
isFinished从bool更改为ManualEventResetSlim就像ManualEventResetSlim isFinished=ManualEventResetSlim ();而不是将其设置为false/true使用Reset/Set然后改为await worker使用isFinished.Wait(Timeout) -
你知道需要多少字节来响应吗?
-
原来我的原始答案完全错误,因为
SerialPort异步 API 完全忽略了超时属性。请检查更新。
标签: c# serial-port