【问题标题】:Using .NET Task.WhenAll when some of the tasks are not started right away在某些任务没有立即启动时使用 .NET Task.WhenAll
【发布时间】:2022-07-08 06:00:51
【问题描述】:

我有一份我想并行执行的作业列表,但其中一些只能在其他作业完成后才能开始。例如:作业 A 和 B 可以立即开始,作业 C 可以在 A 完成后开始,作业 D 可以在 A 和 B 都完成时开始。我事先不知道确切的顺序,因为它来自配置。

我希望我可以创建所有任务,启动其中一些任务,然后在每个任务完成后,检查我是否可以启动其他任务。简化后的代码如下所示:

    public class Job { }
    List<Job> _jobsList; 
    List<Task> _taskList;

    private async Task RunJobs()
    {
        foreach (var job in _jobsList)
        {
            _taskList.Add(new Task(async () => await RunJob(job)));
        }
        StartJobs();
        await Task.WhenAll(_taskList);
    }

    private void StartJobs()
    {
        foreach (var task in _taskList)
        {
            //some logic here to determine which jobs can start now
            if (canstart)
            {
                task.Start();
            }
        }
    }

    private async Task RunJob(Job job) 
    {
        //await some async processing
        StartJobs(); //to start other jobs depending on this one
    }

不幸的是,这不起作用 - Task.WhenAll 在一些任务仍在运行时完成。如果我理解正确,问题是因为 Task 构造函数不能与异步方法一起正常工作,我必须改用 Task.Run 。我能想到的所有解决方法都相当复杂。有没有办法以某种方式简单地实现这一目标?

提前谢谢你。

【问题讨论】:

    标签: .net multithreading async-await


    【解决方案1】:

    该代码按预期工作。

    没有TaskTask&lt;T&gt; 的构造函数接受Func&lt;Task&gt;Func&lt;Task&lt;TResult&gt;&gt;,因此您使用的是Task(Action),它会在代码从操作返回后立即完成。

    几乎没有理由使用TaskTask&lt;T&gt; 的构造函数。其实the remarks

    备注

    这个构造函数只能用于需要将任务的创建和启动分离的高级场景。

    实例化 Task 对象并启动任务的最常见方法是调用静态 Task.Run(Action) 或 TaskFactory.StartNew(Action) 方法,而不是调用此构造函数。

    如果需要一个没有任何操作的任务只是为了让 API 的使用者有一些东西要等待,则应该使用 TaskCompletionSource。

    在这种情况下不需要这些。

    试试这个:

    private async Task RunJobs()
    {
        foreach (var job in _jobsList)
        {
            _taskList.Add(RunJob(job));
        }
        StartJobs();
        await Task.WhenAll(_taskList);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 2013-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多