如果没有标记为异步,Task.Delay是如何等待的?
我正在看Task.Delay(int)
反编译的Task.Delay(int)
:
// System.Threading.Tasks.Task [__DynamicallyInvokable] public static Task Delay(int millisecondsDelay) { return Task.Delay(millisecondsDelay, default(CancellationToken)); }
使用此方法就像await Task.Delay(5000);
,intellisense甚至说“(等待)”:
那么如何将Task.Delay(int)
标记为async
( public static async Task Delay(int millisecondsDelay)
)?
什么是可以接受的Task
Task.Delay
返回。 返回Task
/ Task
每个方法都是等待的。 async
只是一个实现细节,允许您在该方法和它生成的整个状态机中使用await
。
更一般地说,每个具有GetAwaiter
方法( 扩展方法都计数 )的东西都可以等待返回具有IsCompleted
, OnCompleted
和GetResult
东西 。
例如, Task.Yield
返回的YieldAwaitable
不是Task
,如下所示:
public struct YieldAwaiter : ICriticalNotifyCompletion, INotifyCompletion { public void OnCompleted(Action continuation); public void UnsafeOnCompleted(Action continuation); public void GetResult(); public bool IsCompleted { get; } }
*这里的UnsafeOnCompleted
只是一个优化,没有它就await
。
重要的是要注意,在这种情况下编译器(与其他情况相同,如foreach
GetEnumerator
)不期望接口或基类。 它基本上使用duck typing (即“如果它像鸭子一样行走……” )并且只是寻找一个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
。