等待和等待在C#5.0异步
任务或任务对象是等待的,因此我们可以在返回值为Task或Task 的对象上使用await键。 任务或任务是最常用的等待对象。
我们也可以定义我们自己的等待对象。对象应该具有以下资格。
- 它有一个GetAwaiter()方法(实例方法或扩展方法);
- 它的GetAwaiter()方法返回一个awaiter。 在下列情况下,对象是等待者:
- 它实现了INotifyCompletion或ICriticalNotifyCompletion接口;
- 它有一个IsCompleted,它有一个getter并返回一个布尔值;
- 它有一个GetResult()方法,它返回void或结果。
我的问题是为什么微软没有提供限制这些等待对象的界面? 目前实现等待对象的方法有点复杂。
最好在Lucian Wischik的博客文章中回答为什么异步方法必须返回Task?
总而言之(我不是在博客上发布正义,你应该阅读它),问题是Task
已经存在,所以引入一个接口就意味着
- 所有内部方法都需要更改为接口,这是一个中断更改,因此框架人员几乎不可能自愿地做。
- 作为一名程序员,你总是需要决定是否要返回
Task
或界面,这个决定并不重要。 - 编译器总是需要一个具体的类型,所以即使你从一个方法返回一个接口,它仍然会被编译为
Task
。
上述影响非常大,提供界面没有意义。
这与他们为foreach
关键字所做的一致(参见C#语言规范的第8.8.4节“foreach语句”)。
基本上,它是鸭子打字; 如果类型实现了MoveNext
方法和Current
属性,那么C#编译器需要知道如何遍历对象公开的序列。
这也适用于集合初始值设定项(参见C#语言规范“集合初始化程序”的第7.6.10.3节); 唯一的要求是该类型实现System.Collections.IEnumerable
接口并具有Add
方法。
也就是说, await
关键字只是坚持先前的先例,不需要特定的接口实现(尽管如果你选择使用它们,接口会提供这些方法),只是编译器可以识别的方法模式。