Task.WhenAny用法疑问:代码未按预期输出的技术咨询
嘿,我来帮你捋清楚Task.WhenAny的问题~你现在的代码只打印了"0",主要是两个核心原因:一是没循环处理所有完成的任务,二是缺少任务执行阶段的打印逻辑,咱们一步步来修正。
首先拆解你原代码的问题:Task.WhenAny只会返回第一个完成的任务,如果只调用一次,处理完这个任务后剩下的任务根本没被处理,程序可能直接结束,所以看不到后续输出;另外你预期的"1""2",当前代码里完全没加这部分打印逻辑,自然不会输出。
给你改好的代码,关键修正点都标在注释里了:
public async Task PopulateMxRecords(List<string> nsRecords, int threads) { ThreadPool.SetMinThreads(threads, threads); var resolver = new DnsStubResolver(); // 1. 用async lambda包装任务,添加启动时的打印(对应你要的"1""2") var tasks = nsRecords.Select(async ns => { // 如果你的nsRecords刚好是两个元素,也可以直接写Console.WriteLine("1")/Console.WriteLine("2") Console.WriteLine($"{ns} 启动执行(对应预期序号)"); var mxRecords = await resolver.ResolveAsync<MxRecord>(ns, RecordType.Mx); return (Ns: ns, MxRecords: mxRecords); }).ToList(); Console.WriteLine("0"); // 2. 循环处理所有任务,直到没有未完成的任务 while (tasks.Count > 0) { var finishedTask = await Task.WhenAny(tasks); tasks.Remove(finishedTask); // 移除已完成的任务,避免重复处理 try { var result = await finishedTask; // 3. 任务完成后打印每个MX记录的Name foreach (var mx in result.MxRecords) { Console.WriteLine(mx.Name); } } catch (Exception ex) { // 别忘了处理任务可能抛出的异常 Console.WriteLine($"处理域名{result.Ns}时出错:{ex.Message}"); } } }
再给你划几个必须注意的点:
- 把
async void改成async Task:async void一般只用于事件处理场景,改成async Task后调用方可以await这个方法,避免程序在任务还没跑完就提前退出。 - 循环+移除已完成任务:这是用Task.WhenAny处理多任务的标准写法,能确保每个完成的任务都会被处理到。
- 包装任务添加打印:在每个任务启动时加入你要的"1""2"输出,这样就能符合你预期的输出顺序。
这样改完后,程序会先打印"0",然后每个任务启动时打印对应的标识(比如"1""2"),之后每当有任务完成,就会输出该任务拿到的所有mx.Name啦~
内容的提问来源于stack exchange,提问作者user3713080
相关产品推荐
相关产品推荐

