c# 5.0异步中的await和awaiter

本文关键字:await awaiter 异步 | 更新日期: 2023-09-27 17:49:48

任务或任务object是可等待的,所以我们可以对返回值为Task或Task的对象使用await key。任务或任务<结果>是最常用的可等待对象。

还可以定义自己的可等待对象。对象应符合以下条件。

  1. 有一个GetAwaiter()方法(实例方法或扩展方法);
  2. 它的GetAwaiter()方法返回一个await。对象是侍者如果:
      它实现了INotifyCompletion或ICriticalNotifyCompletion接口;
  3. 它有一个IsCompleted,它有一个getter并返回一个布尔值;
  4. 它有一个GetResult()方法,它返回void,或者一个结果。

我的问题是,为什么微软没有提供一个接口来约束这些可等待对象?当前实现可等待对象的方法有点复杂。

c# 5.0异步中的await和awaiter

这个问题在Lucian Wischik的博文中得到了最好的回答:为什么异步方法必须返回Task?

总而言之(我并没有公正地对待这篇博文,你应该阅读它),问题是Task已经存在,所以引入一个接口将意味着

  • 所有的内部方法都需要更改到接口,这是一个中断更改,因此框架人员几乎不可能愿意这样做。
  • 作为一个程序员,你需要不断地决定是返回Task还是返回接口,这个决定并不重要。
  • 编译器总是需要一个具体的类型,所以即使你从一个方法返回一个接口,它仍然会被编译为Task

上面的影响是如此巨大,以至于没有必要提供接口。

这与他们对foreach关键字所做的一致(参见c#语言规范"foreach语句"的第8.8.4节)。

基本上,它是鸭子打字;如果该类型实现了MoveNext方法和Current属性,那么c#编译器就只需要知道如何遍历对象公开的序列。

这也适用于集合初始化器(参见c#语言规范"集合初始化器"第7.6.10.3节);唯一的要求是该类型实现System.Collections.IEnumerable接口并具有Add方法。

也就是说,await关键字只是坚持先前的先例,不需要特定的接口实现(尽管如果您选择使用这些接口,接口提供了这些方法),只是编译器可以识别的方法模式。

我认为主要原因是你在第一点中所说的

实例方法或扩展方法

很简单,因为他们想让用户通过定义一个对象的扩展方法来使它成为可等待的,因此,即使你不拥有一个对象,你也可以使它成为可等待的。

查看此文章