如果Task.Delay没有被标记为异步,它是如何等待的?

时间:2015-01-30 13:17:07

标签: c# .net task-parallel-library async-await ilspy

我正在查看ILSpy中反编译的Task.Delay(int)

// System.Threading.Tasks.Task
[__DynamicallyInvokable]
public static Task Delay(int millisecondsDelay)
{
    return Task.Delay(millisecondsDelay, default(CancellationToken));
}

此方法的使用方式与await Task.Delay(5000);类似,智能感知甚至会说"(等待)":

enter image description here

那么Task.Delay(int)如何标记asyncpublic static async Task Delay(int millisecondsDelay))是怎么回事?

1 个答案:

答案 0 :(得分:19)

Task Task.Delay返回的是什么等待的。返回Task / Task<TResult>的每种方法都是等待的。 async只是一个实现细节,允许您在该方法中使用await以及它生成的整个状态机。

更一般地说,每个的东西都有GetAwaiter方法(extension methods count as well)返回 IsCompleted,{可以等待{1}}和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没有它就可以正常工作。

值得注意的是,在这种情况下编译器(与其他情况相同,如GetEnumerator foreach)并不期望接口或基类。它基本上使用duck typing(即&#34;如果它像鸭子一样行走......&#34; )并且只是查找返回任何内容的GetAwaiter方法(与其他3个成员(IsCompletedOnCompletedGetResult

例如,这就是你可以编译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