7

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

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

这种方法的使用类似于await Task.Delay(5000);,智能感知甚至说“(等待)”:

在此处输入图像描述

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

4

1 回答 1

20

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

更一般地说,每件事都有一个GetAwaiter方法(扩展方法也算在内),它返回的东西IsCompletedOnCompleted并且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 个成员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.

于 2015-01-30T13:23:38.950 回答