Task进度汇报:使用Task.WhenAll()或WaitAll()时如何获取单个任务状态?
当然有办法啦!我来给你分享几个实用的方案,帮你实时追踪每个Task的完成状态:
方案1:给单个Task添加延续操作(ContinueWith)
你可以在每个Task创建后,通过ContinueWith方法附加一个回调,这样当这个Task完成(不管成功还是失败)时,都会立即触发这个回调,你就能在第一时间获知它的状态了。
示例代码:
var tasks = new List<Task>(); foreach (var item in someItems) { var task = DoAsyncWork(item) .ContinueWith(t => { if (t.IsCompletedSuccessfully) { Console.WriteLine($"任务{item}已成功完成,结果:{t.Result}"); } else if (t.IsFaulted) { Console.WriteLine($"任务{item}失败,异常:{t.Exception?.InnerException.Message}"); } else if (t.IsCanceled) { Console.WriteLine($"任务{item}已被取消"); } }, TaskContinuationOptions.ExecuteSynchronously); // 可选:同步执行回调,减少线程切换 tasks.Add(task); } // 等待所有任务(包括延续操作)完成 await Task.WhenAll(tasks);
注意:如果你的回调需要更新UI,记得指定合适的
TaskScheduler(比如TaskScheduler.FromCurrentSynchronizationContext()),避免线程上下文问题。
方案2:使用Task.WhenAny循环逐个处理完成的任务
这种方法更灵活,你可以循环等待第一个完成的Task,处理它的状态后,再从待处理列表中移除,直到所有任务都完成。
示例代码:
var remainingTasks = new HashSet<Task>(someTasks); // someTasks是你的原始任务集合 while (remainingTasks.Count > 0) { var completedTask = await Task.WhenAny(remainingTasks); remainingTasks.Remove(completedTask); // 处理已完成的任务状态 if (completedTask.IsCompletedSuccessfully) { // 如果是带返回值的Task<T>,可以强转后获取结果 var resultTask = completedTask as Task<int>; Console.WriteLine($"任务完成,结果:{resultTask?.Result}"); } else if (completedTask.IsFaulted) { Console.WriteLine($"任务失败,异常:{completedTask.Exception?.InnerException.Message}"); } else if (completedTask.IsCanceled) { Console.WriteLine($"任务已被取消"); } }
这个方案的好处是,你可以实时响应每个任务的完成事件,不需要等到所有任务都结束,而且能清晰地跟踪剩余任务的数量。
补充说明
- 如果你使用的是
Task.WaitAll(同步等待),同样可以用上面的两种方法,只是WaitAll会阻塞当前线程,而await WhenAll是异步等待。 - 对于带返回值的
Task<T>,你可以在回调或循环中强转成对应的泛型Task,获取结果。
内容的提问来源于stack exchange,提问作者Atul Dislay
相关产品推荐
相关产品推荐

