等待异步方法中已完成的任务

时间:2019-12-14 18:27:50

标签: c# asynchronous async-await

当我们调用异步方法时,我们返回一个包装器任务。

public async Task ExecuteActionAsync() {
  // no await called
}
public async Task ExecuteActionAwaitAsync() {
  // await called on a completed
  await Task.CompletedTask;
}
public async Task MyMethod(){
  await ExecuteActionAsync();
  await ExecuteActionAwaitAsync();
}

如果我从不在函数(await)中使用ExecuteActionAsync关键字,或者在我们等待它们时函数(ExecuteActionAwaitAsync)中等待的所有任务已经完成,是否可以保证通过调用这些方法返回的任务将处于完成状态?并且递归地,由MyMethod返回的任务也将处于完成状态,因为它满足了前面提到的条件(等待完成的任务)。我相信我已经读到了可以解决这种情况的优化方法,但是我现在无法在任何地方找到它。

奖金问题:对已完成的任务调用Task.WhenAll是否会返回已完成的任务?

2 个答案:

答案 0 :(得分:5)

可以很容易地对其进行测试:

        var t1 = ExecuteActionAsync();
        Console.WriteLine($"Returned task: {t1.IsCompleted}");
        await t1;
        Console.WriteLine($"Awaited task: {t1.IsCompleted}\n");

        var t2 = MyMethod();
        Console.WriteLine($"Returned task: {t2.IsCompleted}");
        await t2;
        Console.WriteLine($"Awaited task: {t2.IsCompleted}\n");

        t1 = ExecuteActionAsync();
        t2 = MyMethod();

        var t3 = Task.WhenAll(new []{t1,t2 });
        Console.WriteLine($"Task from WhenAll: {t3.IsCompleted}");

结果:

Returned task: True
Awaited task: True

Returned task: True
Awaited task: True

Task from WhenAll: True

所以:是的,如果异步方法同步运行,则返回的任务已完成。是的,从WhenAll通过同步运行的异步方法返回的任务也已完成。

斯蒂芬·克莱里(Stephen Cleary)在这个问题上写了一个有用的blog。具体来说,以下引用是相关的:

  

与其他任何方法一样,执行异步方法的开头。也就是说,它会同步运行,直到遇到“ await”(或引发异常)为止。

     

关键字“ await”是使事物异步的地方。 Await就像一元运算符:它接受一个参数,一个awaitable(“ awaitable”是一个异步操作)。 Await检查该等待项是否已经完成;如果等待已完成,则该方法将继续运行(与常规方法一样同步)。

specifications端处理问题:

  • 异步方法必须返回“ awaitable”类型(例如“ Task”),该类型必须具有“ IsCompleted”属性
  • “ IsCompleted属性的目的是确定任务是否已完成。如果已完成,则无需暂停评估。”

从这些语句可以得出结论,同步运行的异步方法确实会返回完成的Task。

即使执行异步方法时引发异常,返回的Task也将完成(“ IsCompleted”将返回“ true”,尽管“ IsCompletedSuccessfully”将返回“ false”)。

答案 1 :(得分:0)

根据经验,您的所有问题都是肯定的,除了空ExecuteActionAsync()会引起警告,以及空的主体或实际上落在其主体中的其他未等待事物应该同步执行。