Task.Delay 如果未标记为异步,如何等待?
How is Task.Delay awaitable if it's not marked async?
我正在查看 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)
怎么没有被标记为 async
(public static async Task Delay(int millisecondsDelay)
)?
等待的是 Task
Task.Delay
return。 returning Task
/Task<TResult>
的每个方法都是可等待的。 async
只是一个实现细节,允许您在该方法及其生成的整个状态机中使用 await
。
更一般地说,每个 thing 都有一个 GetAwaiter
方法 (extension methods count as well) return something 有 IsCompleted
, OnCompleted
和 GetResult
可以等待。
例如,Task.Yield
returns 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
)不期望接口或基 class。它基本上使用 duck typing(即 "if it walks like a duck...")并简单地寻找一个 GetAwaiter
方法 return 任何东西(无关紧要什么类型或接口,或者如果它是 class 或结构)具有其他 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
到 return 等待的方法,而且 . Net 框架不使用它并显式 return a Task
.
我正在查看 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)
怎么没有被标记为 async
(public static async Task Delay(int millisecondsDelay)
)?
等待的是 Task
Task.Delay
return。 returning Task
/Task<TResult>
的每个方法都是可等待的。 async
只是一个实现细节,允许您在该方法及其生成的整个状态机中使用 await
。
更一般地说,每个 thing 都有一个 GetAwaiter
方法 (extension methods count as well) return something 有 IsCompleted
, OnCompleted
和 GetResult
可以等待。
例如,Task.Yield
returns 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
)不期望接口或基 class。它基本上使用 duck typing(即 "if it walks like a duck...")并简单地寻找一个 GetAwaiter
方法 return 任何东西(无关紧要什么类型或接口,或者如果它是 class 或结构)具有其他 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
到 return 等待的方法,而且 . Net 框架不使用它并显式 return a Task
.