为何这段C#代码输出4个星号而非预期的2个?
问题分析:为何C#代码输出4个星号而非预期的2个?
你的代码核心问题在于**IEnumerable<Task>的延迟执行特性**:
IEnumerable<Task> tasks = Enumerable.Range(0, 2) .Select(_ => Task.Run(() => { Task.Delay(10); Console.Write("*"); }));
IEnumerable<T>是延迟枚举的,这意味着每次你访问这个集合(比如调用Task.WhenAll(tasks)或者tasks.Count()),都会重新执行一遍Select里的逻辑:
- 执行
await Task.WhenAll(tasks)时,会枚举tasks,创建2个新的Task.Run任务,每个任务输出一个*; - 执行
tasks.Count()时,会再次枚举tasks,又创建2个全新的Task.Run任务,这两个任务也会各自输出一个*; - 第二次创建的任务没有被
await,但它们的执行时机刚好会在控制台输出2 stars!前后触发,最终就出现了4个星号的情况。
修复方案
把IEnumerable<Task>转换成立即执行的集合类型(比如List<Task>),确保只创建一次任务:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { List<Task> tasks = Enumerable.Range(0, 2) .Select(_ => Task.Run(() => { // 如果需要实际等待10ms,记得加上await // await Task.Delay(10); Console.Write("*"); })) .ToList(); // 关键:立即执行Select,将结果存入List await Task.WhenAll(tasks); Console.Write($"{tasks.Count()} stars!"); } }
另外提一句:原代码里的Task.Delay(10)没有加await,这个延迟其实不会生效,任务会直接输出*,如果需要真的等待10毫秒再输出,记得加上await关键字。
内容的提问来源于stack exchange,提问作者mnj
相关产品推荐
相关产品推荐

