使用await Task.WhenAll时,如何报告多异步任务的执行进度?
多异步任务完成状态的实时报告实现方案
1. 让状态变更触发事件
首先需要让StatusMessage属性在变更时触发事件,实现INotifyPropertyChanged接口即可:
public class YourClass : INotifyPropertyChanged { private string _statusMessage; public string StatusMessage { get => _statusMessage; set { if (_statusMessage != value) { _statusMessage = value; OnPropertyChanged(nameof(StatusMessage)); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 包装任务,绑定名称并报告完成状态
为每个原始任务添加一层包装,在任务完成(成功/失败)时立即更新状态消息:
// 辅助方法:包装任务并添加状态报告逻辑 private async Task WrapTaskWithCompletionStatus(Task task, string taskName) { try { await task; // 任务成功完成时更新状态 StatusMessage = $"{StatusMessage}\n{taskName} 已完成"; } catch (Exception ex) { // 任务失败时也更新状态(可选) StatusMessage = $"{StatusMessage}\n{taskName} 执行失败:{ex.Message}"; } }
3. 修改点击事件,使用包装后的任务
替换原有的任务列表,用包装后的任务执行并等待:
public async void ButtonClickHandler(object sender, EventArgs e) { // 初始化状态 StatusMessage = "任务开始执行..."; var wrappedTasks = new List<Task> { WrapTaskWithCompletionStatus(Task1, "任务1"), WrapTaskWithCompletionStatus(Task2, "任务2"), WrapTaskWithCompletionStatus(Task3, "任务3"), WrapTaskWithCompletionStatus(Task4, "任务4"), WrapTaskWithCompletionStatus(Task5, "任务5") }; await Task.WhenAll(wrappedTasks); StatusMessage = $"{StatusMessage}\n所有任务执行完毕"; }
4. 扩展:支持任务执行中的进度报告(可选)
如果需要实时获取任务执行中的进度(而非仅完成通知),可以用IProgress<T>接口传递进度信息:
定义进度数据类
public class TaskProgressInfo { public string TaskName { get; set; } public int ProgressPercent { get; set; } public string CurrentStatus { get; set; } }
修改原始任务,支持进度报告
// 示例Task1,添加进度报告逻辑 private async Task Task1(IProgress<TaskProgressInfo> progress) { progress.Report(new TaskProgressInfo { TaskName = "任务1", ProgressPercent = 0, CurrentStatus = "开始执行" }); // 模拟任务步骤 await Task.Delay(1000); progress.Report(new TaskProgressInfo { TaskName = "任务1", ProgressPercent = 50, CurrentStatus = "处理中" }); await Task.Delay(1000); progress.Report(new TaskProgressInfo { TaskName = "任务1", ProgressPercent = 100, CurrentStatus = "已完成" }); }
修改点击事件,处理进度更新
public async void ButtonClickHandler(object sender, EventArgs e) { StatusMessage = "任务开始执行..."; // 创建进度处理器,指定状态更新逻辑 var progressHandler = new Progress<TaskProgressInfo>(UpdateStatusFromProgress); var tasks = new List<Task> { Task1(progressHandler), Task2(progressHandler), Task3(progressHandler), Task4(progressHandler), Task5(progressHandler) }; await Task.WhenAll(tasks); StatusMessage = $"{StatusMessage}\n所有任务执行完毕"; } // 进度更新回调方法 private void UpdateStatusFromProgress(TaskProgressInfo progress) { StatusMessage = $"{StatusMessage}\n[{progress.TaskName}] {progress.CurrentStatus} ({progress.ProgressPercent}%)"; }
关于WorkItem的对应思路
你提到的WorkItem本质是给任务附加元数据(名称、进度等标识信息),我们上面的包装方法、TaskProgressInfo类都是类似思路——把每个任务和它的唯一标识绑定,在状态/进度报告时带上这些信息,就能区分不同任务的状态变更。
内容的提问来源于stack exchange,提问作者Tratak
相关产品推荐
相关产品推荐

