什么时候等待检查等待的?

时间:2017-10-25 22:35:00

标签: c# .net multithreading asynchronous

让我引用Async and Await撰写的Stephen Cleary文章中的代码段及其相关说明,如下所示。

public async Task DoSomethingAsync()
{
     // In the Real World, we would actually do something...
     // For this example, we're just going to (asynchronously) wait 100ms.
     await Task.Delay(100);
}
  

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

     

“await”关键字是事物可以异步的地方。 Await就像一个一元运算符:它需要一个参数,一个等待的(“等待”是一个异步操作)。等待检查等待它是否已经完成;如果等待已经完成,那么该方法就会继续运行(同步,就像常规方法一样)。

     

如果“await”看到等待状态尚未完成,则它会异步进行。它告诉等待在完成时运行方法的其余部分,然后从异步方法返回。

为了适应更一般的情况,让我按如下方式定义代码片段。

public async Task DoSomethingAsync()
{
  AAA();      
  await BBBAsync;
  CCC();
}

其中BBBAsync是唯一的#34;等待"操作或方法。

为简单起见,我们假设我们从主app线程中执行DoSomethingAsync。所以在我的理解中,

  • AAA()将始终同步执行。
  • 无论BBBAsync()如何被调用,
  • DoSomethingAsync()将始终异步执行。
  • CCC()可以异步或同步执行,具体取决于await运算符确定的结果。

在我看来,await运算符总是发现等待尚未完成,因为await总是在BBBAsync()开始之前出现。

问题

什么时候等待检查等待?

1 个答案:

答案 0 :(得分:4)

听起来你认为async使方法异步,而事实并非如此。 Async仅更改方法的代码生成方式,但本身不会添加任何异步步骤,也不会在另一个线程上运行该方法。查看许多问题,例如What is the difference between asynchronous programming and multithreading?

无论是否完成,

await同时检查是否等待 - 像BBBAsync()这样的方法最终会返回Task可能已完成或未完成但方法将返回。

以下是同步完成任务的示例:

 async Task BBBAsync() // ignore CS1998 as we don't want `await` inside
 {
      return;
 }

 // alternatively the same behavior just returning completed Task
 // with FromResult or Task.CompletedTask for 4.6 and later
 Task BB2Async() 
 { 
      return Task.FromResult(0);
 }

您可以等待此类任务,但BBBAsync将同步完成,await将选择同步分支继续。

更现实的样本将同步返回最近缓存的值。此代码将生成用于异步执行的完整状态机,但每个其他调用将同步返回,从而使相应的await同步继续。

 async Task<int> GetValueAsync()
 {
      if (canReturnCached)
      {
         canReturnCached = false;
         return cachedValue;
      }

      cachedValue = await SlowRemoteCallForValueAsync();
      canReturnCached = true;
      return cachedValue;
  }