.NET Core 6 RC1中Task.WhenAll获取不同返回值及判断任务状态的方法
获取不同返回类型的Task执行结果
你当前将所有任务都存入无泛型的List<Task>,丢失了每个Task<T>的泛型类型信息,无法直接从列表中拿到带类型的返回结果,推荐两种实现方案:
方案1:单独持有每个强类型Task的引用(最推荐)
你本来就知晓每个异步方法的返回类型,不需要强行把所有任务丢到无类型列表里丢失类型信息,直接声明对应类型的变量存储即可:
// 声明各任务的强类型变量 Task<List<OrgLocation>> orgLocationsTask = null; if (!string.IsNullOrEmpty(OrgLocationID)) { orgLocationsTask = GetOrgLocations(); } Task<Org> orgTask = GetOrg(); Task<List<RoleType>> roleTypesTask = GetRoleTypes(); Task<UserInfo> userInfoTask = GetOrgOrLocationUserInfo(); // 收集所有任务做批量等待 var allTasks = new List<Task>(); if (orgLocationsTask != null) { allTasks.Add(orgLocationsTask); } allTasks.Add(orgTask); allTasks.Add(roleTypesTask); allTasks.Add(userInfoTask); // 等待所有任务完成 await Task.WhenAll(allTasks); // 直接读取各任务的Result即可,此时任务已完成不会阻塞线程 List<OrgLocation> locations = orgLocationsTask?.Result; Org org = orgTask.Result; List<RoleType> roleTypes = roleTypesTask.Result; UserInfo userInfo = userInfoTask.Result;
方案2:从List中做类型转换
如果你必须从无泛型的任务列表中取值,可以做运行时类型判断转换:
await Task.WhenAll(tasks); foreach (var task in tasks) { if (task is Task<List<OrgLocation>> locTask) { var locations = locTask.Result; // 处理机构位置结果 } else if (task is Task<Org> orgTask) { var org = orgTask.Result; // 处理机构结果 } else if (task is Task<List<RoleType>> roleTask) { var roleTypes = roleTask.Result; // 处理角色类型结果 } else if (task is Task<UserInfo> userTask) { var userInfo = userTask.Result; // 处理用户信息结果 } }
判断部分任务执行失败的方法
可以通过两种方式判断任务执行状态:
方式1:捕获Task.WhenAll抛出的聚合异常
只要有任意任务执行失败/被取消,await Task.WhenAll就会抛出AggregateException,其InnerExceptions属性包含所有失败任务的异常信息:
try { await Task.WhenAll(allTasks); } catch (AggregateException ex) { foreach (var innerEx in ex.InnerExceptions) { // 批量处理所有任务的异常 Console.WriteLine($"任务执行失败:{innerEx.Message}"); } }
方式2:逐个检查任务状态
每个Task实例都自带状态属性,可以逐个判断执行结果,即使部分任务失败,也不影响其他正常完成的任务结果读取:
- IsCompletedSuccessfully:任务正常执行完成,可安全读取Result
- IsFaulted:任务执行抛出异常,异常信息存储在
Exception属性中 - IsCanceled:任务被主动取消,无返回结果
示例代码:
// 以orgLocationsTask为例,其他任务同理判断 if (orgLocationsTask != null) { if (orgLocationsTask.IsCompletedSuccessfully) { var locations = orgLocationsTask.Result; // 处理正常结果 } else if (orgLocationsTask.IsFaulted) { var ex = orgLocationsTask.Exception?.InnerException; // 处理执行失败逻辑 } else if (orgLocationsTask.IsCanceled) { // 处理任务被取消逻辑 } }
注意:即使Task.WhenAll抛出异常,已经正常完成的任务的Result依然可以正常读取,不会丢失。
内容的提问来源于stack exchange,提问作者NSS
相关产品推荐
相关产品推荐

