.NET Core C#中如何分批串行执行异步操作?
.NET Core C# 异步任务分批调度问题:批次串行、批内并行不生效的解决方法
核心问题分析
你当前的代码逻辑完全达不到预期,原因是所有Task在创建时就已经开始执行了,根本没等到分批逻辑的await Task.WhenAll才启动。Task.Delay()一调用就会立即返回一个已在运行的Task,附加ContinueWith也只是给这个运行中的任务加后续操作,整个任务链在你初始化taskArr的时候就全部并行跑起来了。你的分批循环只是在等待这些已经启动的任务陆续完成,完全起不到批次串行调度的作用。
修正方案
要实现「批次间串行、批次内并行」的效果,你需要把任务包装成异步委托(Func<Task>),这样只有当你主动调用委托时,任务才会开始执行。修改后的代码如下:
using System; using System.Threading.Tasks; using System.Collections.Generic; public class Program { public static void Main() { var obj = new Program(); obj.RunAsync().Wait(); } public async Task RunAsync() { const int BATCH_SIZE = 2; // 用Func<Task>包装任务,避免提前执行 var taskFactories = new List<Func<Task>> { async () => { await Task.Delay(TimeSpan.FromSeconds(5.5)); Console.WriteLine("First"); }, async () => { await Task.Delay(TimeSpan.FromSeconds(4.5)); Console.WriteLine("Second"); }, async () => { await Task.Delay(TimeSpan.FromSeconds(0.5)); Console.WriteLine("Third"); }, async () => { await Task.Delay(TimeSpan.FromSeconds(2.5)); Console.WriteLine("Fourth"); }, async () => { await Task.Delay(TimeSpan.FromSeconds(1.5)); Console.WriteLine("Fifth"); }, }; for (var i = 0; i < taskFactories.Count; i += BATCH_SIZE) { var remainingItems = Math.Min(BATCH_SIZE, taskFactories.Count - i); Console.WriteLine("Batch start Idx -> {0} ; Size -> {1}", i, remainingItems); // 启动当前批次的所有任务 var currentBatchTasks = new List<Task>(); for (var j = 0; j < remainingItems; j++) { currentBatchTasks.Add(taskFactories[i + j]()); } // 等待当前批次所有任务完成,再进入下一批次 await Task.WhenAll(currentBatchTasks); } } }
修正后输出(符合预期)
Batch start Idx -> 0 ; Size -> 2 Second First Batch start Idx -> 2 ; Size -> 2 Third Fourth Batch start Idx -> 4 ; Size -> 1 Fifth
关键优化点
- 用
async委托替代直接创建Task,确保任务按需启动,完全受分批逻辑控制 - 批次循环中先启动当前批次的所有任务,再等待完成,严格保证「批内并行、批次串行」
- 移除
ContinueWith,直接在异步委托内编写逻辑,更符合现代C#异步编程的最佳实践,代码可读性更强
内容的提问来源于stack exchange,提问作者Krishnabm
相关产品推荐
相关产品推荐

