.NET 中什么样的类是可使用 await 异步等待的?
我们已经知道 Task 是可等待的,但是去看看 Task 类的实现,几乎找不到哪个基类、接口或者方法属性能够告诉我们与 await 相关。
而本文将探索什么样的类是可使用 await 异步等待的?
Dixin’s Blog - Understanding C# async / await (2) The Awaitable-Awaiter Pattern 一文解决了我们的疑惑。async/await 是给编译器用的,只要我们的类包含一个 GetAwaiter 方法,并返回合适的对象,我们就能让这个类的实例被 await 使用了。
既然需要一个 GetAwaiter 方法,那我们先随便写个方法探索一下:
Test DoAsync()
{
return new Test();
}
class Test
{
void GetAwaiter()
{
}
}
尝试调用:
await DoAsync();
编译器告诉我们:
Test.GetAwaiter() 不可访问,因为它具有一定的保护级别。
原来 GetAwaiter 方法需要是可以被调用方访问到的才行。
于是我们将 GetAwaiter 前面的访问修饰符改成 public。现在提示变成了:
await 要求类型 Test 包含适当的 GetAwaiter 方法。
考虑到一定要获取到某个对象才可能有用,于是我们返回一个 Test2 对象:
public class Test
{
public Test2 GetAwaiter()
{
return new Test2();
}
}
public class Test2
{
}
这时编译器又告诉我们:
Test2 未包含 IsCompleted 的定义。
加上 public bool IsCompleted { get; },编译器又说:
Test2 不实现 INotifyCompletion。
于是我们实现之,编译器又告诉我们:
Test2 未包含 GetResult 的定义。
于是我们加上一个空的 GetResult 方法,现在编译器终于不报错了。
现在我们一开始的 DoAsync 和辅助类型变成了这样:
// 注:此处为试验代码。
private Test DoAsync()
{
return new Test();
}
public class Test
{
public Test2 GetAwaiter()
{
return new Test2();
}
}
public class Test2 : INotifyCompletion
{
public bool IsCompleted { get; }
public void GetResult() { }
public void OnCompleted(Action continuation) { }
}
总结起来,要想使一个方法可被 await 等待,必须具备以下条件:
- 这个方法返回一个类 A 的实例,这个类 A 必须满足后面的条件。
- 此类 A 有一个可被访问到的
GetAwaiter方法(扩展方法也行,这算是黑科技吗?),方法返回类 B 的实例,这个类 B 必须满足后面的条件; - 此类 B 实现
INotifyCompletion接口,且拥有bool IsCompleted { get; }属性、GetResult()方法、void OnCompleted(Action continuation)方法。
更多编写自定义 Awaiter 的文章可以阅读:
入门篇:
- .NET 中什么样的类是可使用 await 异步等待的?
- 定义一组抽象的 Awaiter 的实现接口,你下次写自己的 await 可等待对象时将更加方便
- .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
实战篇:
参考资料
.NET 中什么样的类是可使用 await 异步等待的?的更多相关文章
- .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
林德熙 小伙伴希望保存一个文件,并且希望如果出错了也要不断地重试.然而我认为如果一直错误则应该对外抛出异常让调用者知道为什么会一直错误. 这似乎是一个矛盾的要求.然而最终我想到了一个办法:让重试一直进 ...
- Java Native Interfce三在JNI中使用Java类的普通方法与变量
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 前面我们学习了如何在JNI中通过参数来使用J ...
- 换个新的思路 代替解压jar包 例证:wechat4j 框架中的templateMsg类
很多朋友在写java的程序的时候都喜欢用第三方的jar包和框架,有可能遇到jar包中的内容已经跟不上官方开发者文档的更新,导致部分内容出错了,这个时候可能就要放弃这个jar的使用,但是这个jar中的其 ...
- 标准C++中的string类的用法总结
标准C++中的string类的用法总结 相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有 ...
- 带有静态方法的类(java中的math类)
带有静态方法的类通常(虽然不一定是这样)不打算被初始化. 可以用私有构造函数来限制非抽象类被初始化. 例如,java中的math类.它让构造函数标记为私有,所以你无法创建Math的实例.但Math类却 ...
- java-API中的常用类,新特性之-泛型,高级For循环,可变参数
API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...
- C++中如何定义类和对象?
在C++语言中,对象的类型被称为类,类代表了某一批对象的共性和特征. 类是对象的抽象,而对象是类的具体实例.如同C中的结构体一样,我们要先定义一个结构体,再使用结构体去定义一个变量.同一个结构体可以定 ...
- Oracle数据库中调用Java类开发存储过程、函数的方法
Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日 浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...
- 【转载】C++中的基类与派生类
转自:http://www.cnblogs.com/sujz/articles/2044365.html 派生类的继承方式总结: 继承方式 说明 public 基类的public和protected的 ...
随机推荐
- Java数组的定义和使用
如果希望保存一组有相同类型的数据,可以使用数组. 数组的定义和内存分配 Java 中定义数组的语法有两种: type arrayName[]; type[] arrayName; type 为Java ...
- 介绍 Jersey 依赖
Jersey 使用 Apache Maven 进行构造和安装.非快照(Non-snapshot)Jersey 发行版本是不会部署到 中心 Maven 仓库(Central Maven Reposito ...
- Asp.Net中的sessionState设置
在web.config中有sessionState的节点配置,sessionState共有4中模式:off,inProc,StateServer,SqlServer. 1. off模式 关闭模式,如果 ...
- UVA-12569 Planning mobile robot on Tree (EASY Version) (BFS+状态压缩)
题目大意:一张无向连通图,有一个机器人,若干个石头,每次移动只能移向相连的节点,并且一个节点上只能有一样且一个东西(机器人或石头),找出一种使机器人从指定位置到另一个指定位置的最小步数方案,输出移动步 ...
- 实现自己的ls命令
一步步实现,先看最简单的ls的指令: ls不带参数,直接打印文件名 dst.txt main10.c main11.c main12.c main13.c main14.c~ main15.c~ ma ...
- JavaScript学习总结(一)——JavaScript基础
一.JavaScript语言特点 1.1.JavaScript是基于对象和事件驱动的(动态的) 它可以直接对用户或客户输入做出响应,无须经过Web服务程序.它对用户的响应,是采用以事件驱动的方式进行的 ...
- Java live template[在此处输入文章标题]
Java -Dfile.encoding=UTF-8 提示键盘 功能 Logg private final Logger log = Logger.getLogger(this.getClass()) ...
- PHP:第三章——PHP中表达式函数和匿名函数
<?php header("Content-Type:text/html;charset=utf-8"); //表达式函数和匿名函数 /*$A=function(){ ech ...
- SQL Server 自动化运维系列 - 多服务器数据收集和性能监控
需求描述 在生产环境中,很多情况下需要采集数据,用以定位问题或者形成基线. 关于SQL Server中的数据采集有着很多种的解决思路,可以采用Trace.Profile.SQLdiag.扩展事件等诸多 ...
- Python Django 之 Model
一.Model建表步骤 1. 2. 3. 二.单表的增删改查 1.insert 1)方法一 book.objects.create( title="疯狂外星人", price=10 ...