简体   繁体   English

报告任务进度

[英]Reporting Progress from Tasks

Is there a way to know the status of individual Task while using the WhenAll() or WaitAll() methods of Task. 在使用Task的WhenAll()或WaitAll()方法时,是否有办法了解单个任务的状态。
When I use await Task.WhenAll(tasks.ToArray()) for every task that completes I would like to know that the task has completed. 当我对每个完成的任务使用await Task.WhenAll(tasks.ToArray())时,我想知道该任务已完成。

There is probably a much nicer way to do this, but here is a raw class which takes an array of unstarted tasks and fires an event each time some of the tasks completes execution: 可能有一种更好的方法,但这是一个原始类,该类接收未启动的任务数组,并在每次某些任务完成执行时触发事件:

public class TaskBatchRunner
{
    private Task[] _tasks;

    public event EventHandler<Task> TaskCompleted;

    public TaskBatchRunner(Task[] tasks)
    {
        _tasks = tasks.Select(t =>
            new Task(() =>
            {
                t.ContinueWith(OnTaskCompleted);
                t.Start();
            })).ToArray();
    }

    public void Run()
    {
        foreach (var t in _tasks) t.Start();
        Task.WaitAll(_tasks);
    }

    private void OnTaskCompleted(Task completedTask)
    {
        TaskCompleted?.Invoke(this, completedTask);
    }
}

Usage: 用法:

        var taskRunner = new TaskBatchRunner(tasks.ToArray());
        taskRunner.TaskCompleted += MyTaskCompleted;
        taskRunner.Run();
        ...

    private void MyTaskCompleted(object sender, Task e)
    {
        System.Diagnostics.Debug.WriteLine($"task {e.Id} completed!");
    }

To report progress from an async or concurrent process use the IProgress<T> abstraction. 要报告async或并发进程的进度,请使用IProgress<T>抽象。 Using the Progress<T> implmentation you can easily capture the current context and run your progress update / completion expression on the ui context while doing your work in the background: 使用Progress<T>您可以在后台进行工作时轻松捕获当前上下文并在ui上下文上运行进度更新/完成表达式:

public class WorkItem {
    public async Task DoWork(IProgress<bool> completionNotification) {
        await Task.Delay(TimeSpan.FromSeconds(2));
        //Work Done
        completionNotification.Report(true);
    }

    //Get, Set, Fire Property change etc
    public bool Completed {
        get; set;
    }
}

public class ViewModel {
    public async void ButtonClickHandler(object sender, EventArgs e) {
        var workitemTasks = WorkItems.Select(workItem =>
            workItem.DoWork(new Progress<bool>(done => workItem.Completed = done)))
            .ToList();
        await Task.WhenAll(workitemTasks);
    }

    //Get, Set, Fire Property change etc
    public IEnumerable<WorkItem> WorkItems {
        get; set;
    }
}

More Info 更多信息

Reporting Progress From Async Tasks @StephenCleary 通过异步任务@StephenCleary报告进度

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM