【问题标题】:Why does assigning a Task then awaiting it allow to run in parallel [duplicate]为什么分配一个任务然后等待它允许并行运行[重复]
【发布时间】:2020-11-02 21:29:41
【问题描述】:

我一直在玩异步,我遇到了一些我以前没有注意到的行为,如果这是重复的,请告诉我,但我的 google-fu 让我失望了,主要是因为我可以'想不出合适的搜索词:

给定一个简单的异步方法来做一些参数化的工作:

async Task<String> Foo(int i)
{
    await Task.Delay(i);
    return i.ToString();
}

以及在不同上下文中调用它并捆绑结果的调用方法:

async Task<Object> Bar()
{
    var one =    Foo(3000);
    var two =    Foo(5000);
    var three =  Foo(3000);

    var x =
        new
        {
            One =   await one,
            Two =   await two,
            Three = await three,
        };      
        
    return x;
}

这在 5 秒内完成(在 Linqpad6、.NET Core 3.1 中)。所以我假设每个任务同时运行。

但是,如果我将其更改为在开始时执行 await,它将在 11 秒内完成。所以我假设每个任务都是按顺序运行的。

async Task<Object> Bar()
{
    var one =   await Foo(3000);
    var two =   await Foo(5000);
    var three = await Foo(3000);

    var x =
        new
        {
            One =   one,
            Two =   two,
            Three = three,
        };
        
    return x;
}

我的问题是,分配任务然后等待它,而不是仅仅等待它允许它们并行完成是什么?

【问题讨论】:

  • 它没有。你如何等待任务与它的运行方式无关
  • 这不是区别,区别在于您在等待任何任务之前开始了每个任务。在第二种情况下,您在开始下一个之前等待第一个。这就是区别,而不是它是赋值表达式的一部分。
  • Task 是一个promise,表示某事将在未来完成。它是异步执行的“东西”,并行执行,或者在你的情况下,根本不是 - Task.Delay 创建一个单次触发计时器并返回一个由 TaskCompletionSource 创建的Task,当计时器触发时触发
  • 可能重复:Perform Multiple Async Method Calls Sequentially(可能比现有更好的重复)
  • 对不起,我不完全同意其他 cmets。在我看来,这与分配有关。在第一种情况下,它们并行运行,因为它们在“构建对象时”被等待。在这种情况下,属性是并行分配的......所以任务也以这种方式等待。

标签: c# async-await task-parallel-library


【解决方案1】:

查看队列中的 cmets

async Task<Object> Bar()
{
    var one =    Foo(3000); // <-- It can Start
    var two =    Foo(5000); // <-- It can Start
    var three =  Foo(3000); // <-- It can Start

    var x =
        new
        {
            One =   await one,  // <-- you are waiting for it to finish
            Two =   await two,  // <-- you are waiting for it to finish
            Three = await three,// <-- you are waiting for it to finish
        };      
        
    return x;
}

async Task<Object> Bar()
{
    var one =   await Foo(3000); // <-- you are waiting for it to finish
    var two =   await Foo(5000); // <-- you are waiting for it to finish
    var three = await Foo(3000); // <-- you are waiting for it to finish

    var x =
        new
        {
            One =   one,
            Two =   two,
            Three = three,
        };
        
    return x;
}

【讨论】:

  • 另请注意:var one = await Foo(3000); one 在这里不是Task。这是string
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 2016-10-27
  • 1970-01-01
  • 2012-04-22
  • 2018-08-16
  • 2021-11-23
相关资源
最近更新 更多