让我引用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()
开始之前出现。
什么时候等待检查等待?
答案 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;
}