.NET 7中如何用Task实现带超时的多设备异步初始化?
.NET 7 多设备初始化的Task实现方案
核心思路
- 为每个设备初始化任务单独添加超时控制,避免单个设备无响应阻塞整体流程
- 统一收集所有任务的执行结果(成功、失败、超时),而非依赖
Task.WhenAll的默认异常抛出逻辑 - 根据最终结果集展示对应UI:全成功展示成功界面,否则区分展示失败/超时设备
具体实现代码
定义基础模型
// 设备信息模型 public class DeviceInfo { public string DeviceId { get; set; } = string.Empty; // 可添加其他设备属性,如名称、IP等 } // 初始化结果状态枚举 public enum InitResultStatus { Success, // 初始化成功 Failed, // 初始化失败(抛出异常) Timeout // 初始化超时 } // 设备初始化结果模型 public class DeviceInitResult { public string DeviceId { get; set; } = string.Empty; public InitResultStatus Status { get; set; } public Exception? Exception { get; set; } // 失败时存储异常信息 }
模拟设备初始化方法
// 模拟真实的设备初始化逻辑,可能抛出异常或耗时过长 private async Task InitializeDeviceAsync(DeviceInfo device) { var random = new Random(); // 模拟初始化耗时 await Task.Delay(random.Next(1000, 5000)); // 模拟20%的初始化失败概率 if (random.Next(10) < 2) { throw new InvalidOperationException($"硬件检测失败"); } }
带超时的任务包装方法
// 为单个设备初始化任务添加超时控制,并返回统一结果 private async Task<DeviceInitResult> ExecuteInitWithTimeoutAsync(DeviceInfo device, int timeoutMs) { var initTask = InitializeDeviceAsync(device); var delayTask = Task.Delay(timeoutMs); // 等待初始化任务或超时任务先完成 var completedTask = await Task.WhenAny(initTask, delayTask); if (completedTask == delayTask) { // 超时情况 return new DeviceInitResult { DeviceId = device.DeviceId, Status = InitResultStatus.Timeout }; } try { // 等待初始化任务完成,捕获异常 await initTask; return new DeviceInitResult { DeviceId = device.DeviceId, Status = InitResultStatus.Success }; } catch (Exception ex) { // 初始化失败情况 return new DeviceInitResult { DeviceId = device.DeviceId, Status = InitResultStatus.Failed, Exception = ex }; } }
主流程控制
// 批量处理设备初始化,并根据结果更新UI public async Task ProcessDeviceInitializationAsync(List<DeviceInfo> devices, int timeoutMs = 3000) { // 创建所有带超时控制的初始化任务 var initTasks = devices.Select(device => ExecuteInitWithTimeoutAsync(device, timeoutMs)).ToList(); // 等待所有任务完成,收集全部结果 var allResults = await Task.WhenAll(initTasks); // 分类统计结果 var successDevices = allResults.Where(r => r.Status == InitResultStatus.Success).Select(r => r.DeviceId); var failedResults = allResults.Where(r => r.Status == InitResultStatus.Failed); var timeoutDevices = allResults.Where(r => r.Status == InitResultStatus.Timeout).Select(r => r.DeviceId); // 根据结果更新UI(此处用控制台输出模拟,实际项目替换为UI操作) if (!failedResults.Any() && !timeoutDevices.Any()) { Console.WriteLine("所有设备初始化成功!"); // 展示成功UI逻辑 } else { if (failedResults.Any()) { Console.WriteLine("初始化失败的设备:"); foreach (var result in failedResults) { Console.WriteLine($"- {result.DeviceId}:{result.Exception?.Message}"); } } if (timeoutDevices.Any()) { Console.WriteLine("初始化超时的设备:"); foreach (var deviceId in timeoutDevices) { Console.WriteLine($"- {deviceId}"); } } // 展示错误UI逻辑 } }
关键逻辑说明
- 超时控制:通过
Task.WhenAny对比初始化任务和延迟任务,优先完成的任务决定当前设备的状态,避免单个设备无响应阻塞全局流程。 - 结果收集:使用
Task.WhenAll等待所有任务完成,确保能获取每个设备的最终状态,不会因单个任务异常中断整体流程。 - 状态区分:通过自定义
DeviceInitResult模型,清晰区分成功、失败、超时三种状态,便于后续UI展示逻辑的编写。
内容的提问来源于stack exchange,提问作者Melon NG
相关产品推荐
相关产品推荐

