如何Task.Delay awaitable如果它没有标明异步?Task、Delay、awaitable

2023-09-04 09:41:04 作者:-曾经我也爱过贱人。

我在看 Task.Delay(INT)反编译的ILSpy:

I'm looking at Task.Delay(int) decompiled in ILSpy:

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

此方法用于像等待Task.Delay(5000); ,和智能感知,甚至说(awaitable):

This method is used like await Task.Delay(5000);, and the intellisense even says "(awaitable)":

那么是什么让 Task.Delay(INT)未标记异步公共静态异步任务延迟(INT millisecondsDelay))?

So how is it that Task.Delay(int) isn't marked async (public static async Task Delay(int millisecondsDelay))?

推荐答案

什么是awaitable是工作 Task.Delay 收益。每个方法返回一个工作 / 任务< TResult> 是awaitable。 异步只是一个实现细节,让您使用等待在方法和整个国家机器它产生。

What's awaitable is the Task Task.Delay returns. Each method returning a Task/Task<TResult> is awaitable. async is just an implementation detail allowing you to use await in that method and the whole state machine it generates.

更一般地,每一个的的事的,有一个 GetAwaiter 办法(的扩展方法计算,以及),其收益的的东西的,有 IsCompleted OnCompleted 调用getResult 可以期待已久的。

More generally, every thing that has a GetAwaiter method (extension methods count as well) that return something that has IsCompleted, OnCompleted and GetResult can be awaited.

例如, Task.Yield 返回 YieldAwaitable 这是不是一个工作,看起来是这样的:

For example, Task.Yield returns YieldAwaitable which isn't a Task and looks like this:

public struct YieldAwaiter : ICriticalNotifyCompletion, INotifyCompletion
{
    public void OnCompleted(Action continuation);
    public void UnsafeOnCompleted(Action continuation);
    public void GetResult();
    public bool IsCompleted { get; }
}

* UnsafeOnCompleted 在这里仅仅是一个优化,等待将工作没有它。

*UnsafeOnCompleted here is just an optimization, await would work without it.

要注意的是,编译器在这种情况下,重要的是(同在其他情况下,像的GetEnumerator 的foreach )不期望的接口或基类。它主要采用鸭打字(即如果走路像鸭子...... 的),只是寻找一个 GetAwaiter 方法,返回任何东西(无所谓什么类型或接口,或者如果它是一个类或结构)具有其他3名成员( IsCompleted OnCompleted 调用getResult

It's important to note that the compiler in this case (same as in other cases like GetEnumerator for foreach) doesn't expect an interface or a base class. It basically uses duck typing (i.e. "if it walks like a duck...") and simply looks for a GetAwaiter method that returns anything (doesn't matter what type or interface or if it's a class or a struct) that has the other 3 members (IsCompleted, OnCompleted and GetResult)

例如,这是你如何让等待酒吧编译(它将当然运行失败):

For example, this is how you can make await "bar" compile (it will fail in runtime of course):

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);
}

总之,你不需要异步返回一个awaitable而且最工作 - 返回方法在.NET Framework中不使用它,并明确地返回一个工作

In conclusion, you don't need async to return an awaitable and moreover most Task-returning methods in the .Net framework don't use it and explicitly return a Task.