等待的是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没有它也可以。
需要注意的是,这种情况下的编译器(与GetEnumeratorfor等其他情况相同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.