等待的是Task
Task.Delay
回报。每个返回Task
/的方法Task<TResult>
都是可等待的。async
只是一个实现细节,允许您await
在该方法及其生成的整个状态机中使用。
更一般地说,每件事都有一个GetAwaiter
方法(扩展方法也算在内),它返回的东西有IsCompleted
,OnCompleted
并且GetResult
可以等待。
例如,Task.Yield
返回YieldAwaitable
不是 aTask
并且看起来像这样:
public struct YieldAwaiter : ICriticalNotifyCompletion, INotifyCompletion
{
public void OnCompleted(Action continuation);
public void UnsafeOnCompleted(Action continuation);
public void GetResult();
public bool IsCompleted { get; }
}
*UnsafeOnCompleted
这只是一个优化,await
没有它也可以。
需要注意的是,这种情况下的编译器(与GetEnumerator
for等其他情况相同foreach
)不需要接口或基类。它基本上使用鸭子类型(即“如果它像鸭子一样走路......”)并简单地寻找一个GetAwaiter
返回任何东西的方法(不管是什么类型或接口,或者它是一个类还是一个结构)具有另一个3 个成员IsCompleted
(OnCompleted
和GetResult
)
例如,这是您可以await "bar"
编译的方式(当然它会在运行时失败):
public static Awaiter GetAwaiter(this string s)
{
throw new NotImplementedException();
}
public abstract class Awaiter : INotifyCompletion
{
public abstract bool IsCompleted { get; }
public abstract void GetResult();
public abstract void OnCompleted(Action continuation);
}
总之,您不需要async
返回可等待的,而且.Net 框架中的大多数Task
返回方法都不会使用它并显式返回Task
.