【问题标题】:Do a Task's continuations run async to each other?任务的延续是否彼此异步运行?
【发布时间】:2023-03-16 05:30:01
【问题描述】:

我已经搜索过,但在任何地方都找不到明确的确认...如果一个任务有多个延续(不是链式延续),这些延续是否彼此并行运行?

我想运行 task1,然后是 task2-task3-task4 彼此并行运行,最后是 task5,当所有都完成时。下面的例子。任务 2、3 和 4 肯定会彼此异步运行吗?

在此过程中,欢迎提出任何改进模式的建议。似乎有几种不同的方法可以完成这种组合。谢谢

public Task MyWorkflowAsync() {
  Task task1 = Task.Factory.StartNew( () => DoTask1() );

  var tarray = new Task[] {
    task1.ContinueWith( task => DoTask2() ),
    task1.ContinueWith( task => DoTask3() ),
    task1.ContinueWith( task => DoTask4() )
  };

  return Task.Factory.ContinueWhenAll( tarray, completedTasks => DoTask5() );
}

【问题讨论】:

    标签: .net task-parallel-library


    【解决方案1】:

    不,延续是由默认调度程序以 LIFO 顺序执行的。如果你想让它们全部并行运行,你应该这样做:

    public Task MyWorkflowAsync()
    {
        var tasks = new List<Task>();
        var task1 = Task.Factory.StartNew(DoTask1);
    
        tasks.Add(task1.ContinueWith(task => tasks.Add(Task.Factory.StartNew(DoTask2))));
        tasks.Add(task1.ContinueWith(task => tasks.Add(Task.Factory.StartNew(DoTask3))));
        tasks.Add(task1.ContinueWith(task => tasks.Add(Task.Factory.StartNew(DoTask4))));
    
        return Task.Factory.ContinueWhenAll(tasks.ToArray(), completedTasks => DoTask5());
    }
    

    【讨论】:

    • 呸。不是我希望的答案:-) 我明白为什么有必要添加内部 DoTasks,但为什么还需要添加外部 ContinueWith 任务?在您的示例中,任务最终有 6 个成员而不是 3 个,对吗?
    • 我正在考虑这一点,您可能不必添加外层。试一试。
    • 所以我听从了您的建议并试了一下。看起来我原来的帖子的模式会给我我需要的东西。我用随机睡眠持续时间和毫秒精度的时间戳(包括它们的 ManagedThreadID)填充了 DoTask 方法。 DoTask2-4 总是以看似随机的顺序在单独的线程上彼此相隔几毫秒开始。 DoTasks 按照它们的睡眠时间顺序完成。总运行时间最长的是 2-4,再加上 1 和 5 的开销。此外,5 始终与运行时间最长的 2-4 在同一线程上运行。
    • 我相信要获得 Jesse 在他的帖子中描述的行为,您需要将 TaskContinuationOptions.ExecuteSynchronously 传递给 Task.ContinueWith()。来自doco:“指定应同步执行延续任务。指定此选项后,延续将在导致前项任务转换到其最终状态的同一线程上运行。如果在延续时前项已经完成被创建后,延续将在创建延续的线程上运行。只有运行时间很短的延续应该同步执行。"
    猜你喜欢
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2018-10-18
    • 2010-10-25
    • 2018-09-12
    相关资源
    最近更新 更多