You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将等待调制解调器就绪的函数改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:08:30