async 的三大返回类型
序
博主简单数了下自己发布过的异步文章,已经断断续续 8 篇了,这次我想以 async 的返回类型为例,单独谈谈。
异步方法具有三个可让开发人员选择的返回类型:Task<TResult>、Task 和 void。
什么时候需要使用哪一种返回类型,具体情况需要具体分析。如果使用不当,程序的执行结果也许并不是你想要的,下面我们就来好好谈谈如何针对不同的情况选择不同的返回类型。
目录
- 返回类型 - Task<TResult>
- 返回类型 - Task
- 返回类型 - void
- 小结
一、返回类型 - Task<TResult>
【记住】当你添加 async 关键字后,需要返回一个将用于后续操作的对象,请使用 Task<TResult>。
Task<TResult> 返回类型可用于 async 方法,其中包含指定类型 TResult。
在下面的示例中,GetDateTimeAsync 异步方法包含一个返回当前时间的 return 语句。 因此,方法声明必须指定 Task<DateTime>。
async Task<DateTime> GetDateTimeAsync()
{
//Task.FromResult 是一个占位符,类型为 DateTime
return await Task.FromResult(DateTime.Now);
}
调用 GetDateTimeAsync 方法:
async Task CallAsync()
{
//在另一个异步方法的调用方式
DateTime now = await GetDateTimeAsync();
}
当 GetDateTimeAsync 从 await 表达式中调用时,await 表达式将检索存储在由 GetDateTimeAsync 返回的 task 中的 DateTime 类型值。

async Task CallAsync()
{
//在另一个异步方法的调用方式
//DateTime now = await GetDateTimeAsync(); //换种方式调用
Task<DateTime> t = GetDateTimeAsync();
DateTime now = await t;
}

通过 CallAsync 方法对 GetDateTimeAsync 方法的调用,对非立即等待的方法 GetDateTimeAsync 的调用返回 Task<DateTime>。 该任务指派给示例中的 DateTime 的 Task 变量。 因为 DateTime 的 Task 变量是 Task<DateTime>,也就是说这里的 TResult 就是 DateTime 类型。 在这种情况下,TResult 表示日期类型。 当 await 应用于 Task<DateTime>,await 表达式的计算结果为 Task<DateTime> 的 DateTime 类型的内容。同时,该值会分配给 now 变量。
这次我演示不同的变量,你可以自己对比下结果是否相同:

async Task CallAsync()
{
//在另一个异步方法的调用方式
DateTime now = await GetDateTimeAsync(); //换种方式调用
Task<DateTime> t = GetDateTimeAsync();
DateTime now2 = await t;
//输出的结果对比
Console.WriteLine($"now: {now}");
Console.WriteLine($"now2: {now2}");
Console.WriteLine($"t.Result: {t.Result}");
}

我这边可以给出的答案就是:结果是一样的。
【注意】task 的 Result 属性为锁定属性。如果你在该 task 完成之前尝试读取该属性值,会出现的结果是,当前处于活动状态的 thread 将被阻塞,阻塞到该 task 完成且结果值为可用时。 在大多数情况下,你都应通过使用 await 访问属性值,而不是直接访问该属性。
二、返回类型 - Task
【记住】你如果只是想知道执行的状态,而不需要知道具体的返回结果时,请使用 Task。
不包含 return 语句,或者说不包含返回值的 return 语句的 async 方法通常具有返回类型 Task。如果这样的同步方法被编写为 async 的,这些方法实际上也是返回 void 的方法。 如果在异步方法中使用 Task 返回类型,调用方法可以使用 await 运算符暂停调用方的完成,直至被调用的 async 方法结束。
请看示例:

async Task DelayAsync()
{
//Task.Delay 是一个占位符,用于假设方法正处于工作状态。
await Task.Delay(100); Console.WriteLine("OK!");
}

通过使用 await 语句而不是 await 表达式来调用和等待 DelayAsync 方法,类似于返回 void 的方法的调用语句。 await 运算符的应用程序在这种情况下不生成值。
请看调用 DelayAsync 的示例。
//调用和等待方法在同一声明中
await DelayAsync();
现在,我用将调用和等待的方法进行分离:
//分离
Task delayTask = DelayAsync(); await delayTask;
三、返回类型 - void
【记住】如果在触发后,你不想管了,请使用 void。如事件处理程序。
void 返回类型主要用在事件处理程序中。 void 返回类型还可用来替代不返回任何东西的方法,或者用于执行可分类为"调用后不管了"活动的方法。 但是,你都应尽可能地返回类型 Task ,因为,不能 await 返回类型为 void 的 async 方法。 async 方法的任何调用方只能够继续完成(意味着有可能会出现 thread 阻塞),而无需等待调用的 async 方法完成,并且调用方应该,或者说必须独立于 async 方法生成的任何值或 exception。
返回 void 的 async 方法的调用方无法 catch 从该方法引发的 exception,并且,这种未经处理的 exception 可能会导致你的程序出现难以发现的故障。 如果返回 Task 类型或 Task<TResult> 类型的 async 方法中出现 exception,这种 exception 将存储于返回的任务中,并将在 await 该任务时再次触发。也就是说,请尽量优先使用 Task<TResult> 和 Task,这样,调用方才能从中读取异常信息,并选择如何处理。
现在,异常也可以使用 await 了,请移步到这里 《回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性》。
void 返回值示例:
private async void button1_Click(object sender, EventArgs e)
{
//启动进程并等待完成
await Task.Delay(100);
}
小结
当你添加 async 关键字后,需要返回一个将用于后续操作的对象,请使用 Task<TResult>;
你如果只是想知道执行的状态,而不需要知道具体的返回结果时,请使用 Task;
如果在触发后,你不想管了,请使用 void。
- 请尽量优先使用 Task<TResult> 和 Task 作为 async 方法的返回类型。
async 的三大返回类型的更多相关文章
- [C#] async 的三大返回类型
async 的三大返回类型 序 博主简单数了下自己发布过的异步文章,已经断断续续 8 篇了,这次我想以 async 的返回类型为例,单独谈谈. 异步方法具有三个可让开发人员选择的返回类型:Task&l ...
- asp.net core系列 38 WebAPI 返回类型与响应格式--必备
一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...
- springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序 http://www.360doc.com/content/14/03 ...
- MySql学习 (一) —— 基本数据库操作语句、三大列类型
注:该MySql系列博客仅为个人学习笔记. 在使用MySql的时候,基本都是用图形化工具,如navicat.最近发现连最基本的创建表的语法都快忘了... 所以,想要重新系统性的学习下MySql,为后面 ...
- C/C++函数调用的几种方式及函数名修饰规则以及c++为什么不允许重载仅返回类型不同的函数
我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预 ...
- C# web api返回类型设置为json的两种方法
web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...
- 转:C++编程隐蔽错误:error C2533: 构造函数不能有返回类型
C++编程隐蔽错误:error C2533: 构造函数不能有返回类型 今天在编写类的时候,出现的错误. 提示一个类的构造函数不能够有返回类型.在cpp文件里,该构造函数定义处并没有返回类型.在头文件里 ...
- iOS 用instancetype代替id作返回类型有什么好处?
2014-07-07更新:苹果在iOS 8中全面使用instancetype代替id Steven Fisher:只要一个类返回自身的实例,用instancetype就有好处. @interface ...
- C# web api 返回类型设置为json的两种方法
每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...
随机推荐
- 自定义基于XML的验证器
a.编写一个类,继承FieldValidatorSupport类. b.在public void validate(Object object)编写你的验证逻辑 不符合要求的就向fieldErrors ...
- 比较R语言、perl语言,matlab中for循环和while循环的使用
http://zhan.renren.com/zxccshkbx?gid=3602888498030523562&from=post&checked=true
- Navicat Premium 快捷键
1.ctrl+q 打开查询窗口2.ctrl+/ 注释sql语句3.ctrl+shift +/ 解除注释4.ctrl+r 运行查询窗口的sql语句5.ctrl+shift+r 只运行选中的sql语句6. ...
- Java分布式 一些概念理解
转至 java那些事 2017-02-09 有些朋友工作一年了觉得该深入一下子了,所以想深入学习一下以提升自己的专业技能,想问一下如何入门Java分布式应用,学习过程大致是怎么样的,涉及到那些知识, ...
- yii xss模型安全
在这篇文章里,我们将描述一个基于WEB应用下避免不合法的内容注入. 我们要在一个行为里使用htmlpurifier类,用这种行为可以加强任何模型并表明各属性我们想让它们XSS安全. 我写了以下行为: ...
- [gj]耶稣和撒旦的关系
转: https://zhidao.baidu.com/question/7461904.html 人生充满试探,无论你居住在乡间或城市,都尝会受到试探,耶稣在世上的日子,也受到试探,让我们看看两处经 ...
- Java中数据库连接的一些方法资料汇总
Java中Connection方法笔记 http://www.cnblogs.com/bincoding/p/6554954.html ResultSet详解(转) https://www.cnbl ...
- url参数
两个参数情况: String url="http://59.78.93.208:9097/Order?id="+id+"&value="+value; ...
- display:flex和display:box布局浏览器兼容性分析
display:flex和display:box都可用于弹性布局,不同的是display:box是2009年的命名,已经过时,用的时候需要加上前缀:display:flex是2012年之后的命名.在实 ...
- Java 使用 HttpClient调用https 最新源码 JDK7+ apache4.3+
在项目使用https方式调用别人服务的时候,以前要写很多的代码,现在框架封装了很多,所以不用再写那么多了. 网上看了一下,都是很老的版本,用过时的DefaultHttpClient. 以spring为 ...