You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:37:07