【问题标题】:When does await examine the awaitable?await 什么时候检查 awaitable?
【发布时间】:2017-10-25 22:34:59
【问题描述】:

下面我引用Async and AwaitStephen Cleary写的文章中的代码sn-p及其相关解释如下。

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 检查 awaitable 是否已经完成;如果 awaitable 已经完成,则该方法继续运行(同步地,就像常规方法一样)。

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

为了适应更一般的情况,让我将代码 sn-p 定义如下。

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

其中BBBAsync 是唯一的“可等待”操作或方法。

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

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

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

问题

await 什么时候检查 awaitable?

【问题讨论】:

    标签: c# .net multithreading asynchronous


    【解决方案1】:

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

    await 会同时检查 awaitable,无论它是否已完成 - 像 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;
      }
    

    【讨论】:

    • 您的示例应该是 return; 定义中带有 asyncreturn Task.FromResult(0);(或 Task.CompletedTask 对于 4.6 及更高版本)不带 async
    猜你喜欢
    • 2021-06-23
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多