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

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

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是否会返回已完成的任务?

参考方案

这很容易测试:

        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

因此:是的,如果async方法同步运行,则返回的Task已完成。是的,从WhenAll返回的传递同步运行的异步方法的任务也已完成。
Stephen Cleary在此主题上写了有用的blog。具体来说,以下引用是相关的:

异步方法的开始就像其他方法一样被执行。也就是说,它将同步运行,直到达到“ await”(或引发异常)为止。
“ await”关键字是事物可以异步进行的地方。 Await就像一元运算符:它接受一个参数,一个awaitable(一个“ awaitable”是一个异步操作)。等待检查该等待项是否已经完成;如果等待已完成,则该方法将继续运行(同步,就像常规方法一样)。

从specifications方面处理问题:

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

从这些语句可以得出结论,同步运行的异步方法确实将返回完成的Task。
即使在执行async方法时引发异常,返回的Task也将完成(“ IsCompleted”将返回“ true”,尽管“ IsCompletedSuccessfully”将返回“ false”)。

了解C#等待运算符 - c#

我只是对C#的异步编程有一些基本的了解。据我了解,这段代码statement1; await statement2(); statement3; statement4; 在逻辑上应等效于statement1; var awaiter = statement2().GetAwaiter(); awaiter.OnCompletion(() => { aw…

多重处理:map与map_async - python

使用map和map_async有什么区别?将列表中的项目分配给4个进程后,它们是否运行相同的功能?因此,假设两者都在异步和并行运行是错误的吗?def f(x): return 2*x p=Pool(4) l=[1,2,3,4] out1=p.map(f,l) #vs out2=p.map_async(f,l) python大神给出的解决方案 将作业映射到流程…

如何正确地将HttpClient与async / await一起使用? - c#

以下代码出现两个错误:public async Task<string> TestDownloadTask() { HttpResponseMessage response = null; using (HttpClient client = new HttpClient()) { client.BaseAddress = new Uri(@&#…

在单独的ThreadPool中执行某些后台任务,以避免饿死于在主线程中执行的关键任务 - c#

在单独的ThreadPool中执行某些后台任务(非线程),以避免饿死于在主线程中执行的关键任务(非线程)我们的方案我们托管一个高容量的WCF Web服务,该服务在逻辑上具有以下代码:void WcfApiMethod() { // logic // invoke other tasks which are critical var mainTask = Ta…

任务工厂的每个循环等待 - c#

我是新手,对用法有疑问。 Task.Factory是否会在foreach循环中或在“等待”时阻塞所有项目,从而基本上使程序成为单线程?如果我正确地考虑了这个问题,则foreach循环将启动所有任务,然后执行.GetAwaiter()。GetResult();。正在阻塞主线程,直到最后一个任务完成。另外,我只是想要一些匿名任务来加载数据。这是正确的实施方式吗?…