关于任务创建与分组任务执行顺序的技术问询
任务创建与分组任务执行顺序的技术问询
嘿,我完全get到你这个有点特别的需求了——每个分组里的任务都要启动,但必须保证该分组的最后一个值对应的任务是最后执行的,对吧?我来给你分享几个靠谱的实现思路,都是异步场景下的常规操作。
首先,核心思路就是把每个分组的元素拆成两部分:除最后一个之外的所有元素,以及最后一个元素。我们要确保同一分组里,前面的任务全部完成后,再启动最后那个任务,不同分组之间的任务可以正常并行。
先给你看第一种实现方式,直接在原方法里调整逻辑:
public async Task DoAllTheWork(IEnumerable<IGrouping<string, string>> groups) { var allTasks = new List<Task>(); foreach (var group in groups) { var values = group.ToList(); if (values.Count == 0) continue; // 空分组直接跳过,避免报错 // 先启动当前分组里除最后一个之外的所有任务 var nonLastTasks = values.Take(values.Count - 1) .Select(val => ExecuteSingleTask(val)) // 这里替换成你实际执行单个内容的方法 .ToList(); allTasks.AddRange(nonLastTasks); // 确保当前分组的非最后任务都完成后,再执行最后一个任务 var lastTask = Task.WhenAll(nonLastTasks) .ContinueWith(_ => ExecuteSingleTask(values.Last()), TaskContinuationOptions.OnlyOnRanToCompletion) .Unwrap(); allTasks.Add(lastTask); } // 等待所有分组的所有任务全部完成 await Task.WhenAll(allTasks); } // 示例:单个任务的执行逻辑,你可以根据实际需求修改 private async Task ExecuteSingleTask(string value) { // 这里写每个内容对应的异步操作,比如调用API、处理文件等 Console.WriteLine($"正在执行任务:{value}"); await Task.Delay(100); // 模拟耗时操作 }
这种写法的好处是把所有任务都统一管理在allTasks列表里,最后一起等待完成。ContinueWith和Unwrap的组合能保证最后一个任务只会在当前分组的其他任务都成功完成后才启动。
如果你觉得上面的写法有点绕,还有一种更清晰的方式——把单个分组的处理逻辑抽成独立方法,代码可读性会更好:
public async Task DoAllTheWork(IEnumerable<IGrouping<string, string>> groups) { var groupProcessingTasks = new List<Task>(); foreach (var group in groups) { // 每个分组的处理作为一个独立任务,各组之间并行执行 var processGroupTask = ProcessSingleGroupAsync(group); groupProcessingTasks.Add(processGroupTask); } // 等待所有分组的处理任务完成 await Task.WhenAll(groupProcessingTasks); } private async Task ProcessSingleGroupAsync(IGrouping<string, string> group) { var values = group.ToList(); if (values.Count == 0) return; // 先等待当前分组里除最后一个之外的所有任务完成 var nonLastTasks = values.Take(values.Count - 1) .Select(ExecuteSingleTask) .ToList(); await Task.WhenAll(nonLastTasks); // 最后执行当前分组的最后一个任务 await ExecuteSingleTask(values.Last()); } // 同样,这里是单个任务的执行逻辑 private async Task ExecuteSingleTask(string value) { Console.WriteLine($"正在执行任务:{value}"); await Task.Delay(100); }
这种写法把分组内的顺序逻辑封装在ProcessSingleGroupAsync里,主方法只需要管理各个分组的并行,代码结构更清晰,后期维护也方便。
两种写法都能满足你的需求,你可以根据自己的代码风格和实际场景来选。如果你的分组数量很多,两种方式的性能差异不大,因为都是利用异步并行来提高效率的。
备注:内容来源于stack exchange,提问作者pseudodev
相关产品推荐
相关产品推荐

