如何将等待调制解调器就绪的函数改为async并实现超时机制?
改造异步等待函数并实现超时逻辑
第一步:重构原等待函数为真正的异步实现
原函数用Thread.Sleep阻塞线程+同步轮询TryRead,效率低且不符合异步规范,改成基于ChannelReader.ReadAsync的异步版本:
private async Task WaitForReadyForSMSDataAsync(CancellationToken cancellationToken = default) { while (true) { // 异步等待Channel中出现数据,不会阻塞线程 var modemData = await _sendSMSChannel.Reader.ReadAsync(cancellationToken); // 判断是否是目标信号 if (modemData.ModemMessageClasses.Contains(ModemDataClass.ReadyForSMSData)) { break; } // 非目标信号则继续等待下一条数据 } }
第二步:结合超时逻辑调用
用Task.WhenAny结合异步等待函数和延迟任务,实现超时判断,同时用CancellationTokenSource确保超时后能终止Channel的读取操作:
// 设置超时时间(毫秒) int timeoutMs = 1000; using var cts = new CancellationTokenSource(); cts.CancelAfter(timeoutMs); try { var waitTask = WaitForReadyForSMSDataAsync(cts.Token); var delayTask = Task.Delay(timeoutMs, cts.Token); var completedTask = await Task.WhenAny(waitTask, delayTask); if (completedTask == waitTask) { // 确保等待过程中若有异常能正确抛出 await waitTask; // 这里写收到就绪信号后的SMS发送逻辑 Console.WriteLine("调制解调器已就绪,开始发送SMS"); } else { // 超时处理逻辑 throw new TimeoutException("等待调制解调器就绪信号超时"); } } catch (OperationCanceledException) { // 捕获取消信号,统一转为超时异常 throw new TimeoutException("等待调制解调器就绪信号超时"); }
关键注意点
- 替换
async void为async Task:async void仅适用于UI事件处理器,普通异步操作返回Task才能被正确等待、捕获异常 - 用
ReadAsync替代同步轮询:异步等待Channel数据,避免线程阻塞,提升程序响应性 - 配合
CancellationToken:超时后自动取消读取操作,避免资源浪费,同时统一处理取消/超时场景
内容的提问来源于stack exchange,提问作者jeppe
相关产品推荐
相关产品推荐

