使用Task.WhenAll()等待异步任务后赋值时如何避免重复检查条件
C#异步代码避免重复条件判断的优化方案
以下两种优化方案均无需重复编写两次条件判断,也不需要使用Task.Run,同时完全保留原代码并行执行异步任务的特性:
方案1:封装分支处理逻辑(适合分支较少的场景)
将每个条件分支的异步执行+赋值逻辑绑定封装,仅需要一次条件判断,无需声明额外的临时Task变量:
var tasks = new List<Task>(); if (myCondition) { async Task AssignFoo() => result.foo = await getAsync(); tasks.Add(AssignFoo()); } if (myOtherCondition) { async Task AssignBar() => result.bar = await getAsync2(); tasks.Add(AssignBar()); } await Task.WhenAll(tasks);
该方案和原代码执行逻辑完全等价,所有符合条件的异步任务会并行启动,全部执行完成后才会继续后续流程。
方案2:统一配置处理规则(适合分支较多、需要扩展的场景)
把条件判断、异步取值方法、赋值逻辑封装为配置统一管理,新增分支仅需要添加一条配置即可,全程无需重复编写判断逻辑:
// 统一配置所有分支规则:判断条件、异步取值方法、赋值逻辑 var taskConfigs = new List<(bool IsEnabled, Func<Task<string>> GetValue, Action<string> SetValue)> { (myCondition, getAsync, val => result.foo = val), (myOtherCondition, getAsync2, val => result.bar = val) }; // 过滤符合条件的分支,并行执行所有任务 await Task.WhenAll(taskConfigs .Where(config => config.IsEnabled) .Select(async config => config.SetValue(await config.GetValue())) );
对齐原代码行为的兼容方案
如果需要严格保留原代码「所有任务全部完成后才统一赋值」的特性(避免部分任务先完成提前赋值引发的并发问题),可以使用以下写法:
var pendingTasks = new List<(Task<string> ValueTask, Action<string> SetValue)>(); if (myCondition) { pendingTasks.Add((getAsync(), val => result.foo = val)); } if (myOtherCondition) { pendingTasks.Add((getAsync2(), val => result.bar = val)); } // 先等待所有任务执行完成 await Task.WhenAll(pendingTasks.Select(t => t.ValueTask)); // 统一批量赋值,和原代码行为100%一致 foreach (var taskItem in pendingTasks) { // 此处await不会产生等待,任务已经执行完成 taskItem.SetValue(await taskItem.ValueTask); }
内容的提问来源于stack exchange,提问作者jmn
相关产品推荐
相关产品推荐

