前言

C# 中的 Async 和 Await 关键字是异步编程的核心。使用这两个关键字可以轻松创建异步方法。使用 async 关键字定义的异步方法简称“异步方法”。

异步编程

并发的一种形式,它采用furture模式或回调(callback)机制,以避免产生不必要的线程。.Net中future的类型有 TaskTask<Result>

异步编程的核心理念是异步操作:

启动了的操作将会在一段时间后完成。

这个操作正在执行时,但不会阻塞原来的线程。

启动了这个操作的线程后,可以继续执行其它任务。

当操作完成时,它会通知它的future,或者调用回调函数,以便让程序知道操作已经结束。

异步的好处

  1. 对于面向终端用户的GUI程序,异步可以提高响应能力。

  2. 对于服务器应用:异步编程实现了可扩展。

    服务器可以利用线程池填满其可扩展性,使用异步编程后,可扩展性通常可以提供一个数量级,可以最大程度的压榨服务器性能,提高处理能力。

async

使用 async 修饰符可以将方法、lambda表达式或匿名方法指定为异步。

async 的主要目的是,使方法内的await关键字生效。

//等待异步完成再执行后边的操作,但是整个方法不会阻塞
var result = await DoSomethingAsync();
output.Result = result;

如果使用了 Async 最好一直使用它

await

async 标记的异步方法,可以使用 await 来指定暂定点。await 运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方

async 方法在开始时以同步的方式执行。在 async 方法内部,await 关键字对他的参数(一个异步任务)执行一个异步等待。它首先检查操作是否已经完成,如果完成了,就继续运行(同步方法)。否则,他会暂停 async 方法,并返回,将控制权交给调用方,留下一个 未完成的 Task。一段时间后,操作完成,async方法再恢复运行。

await 语句等待一个任务完成,当该方法在 await 处暂停时,就可以捕捉上下文(context)。如果当前SynchronizationContext不为空,这个上下文就是当前SynchronizationContext。如果当前SynchronizationContext为空,则这个上下文为当前TaskScheduler。该方法会在这个上下文中继续运行。

//此时await会捕获当前上下文
await DoSomethingAsync();
//....    //这里会试图用上边捕获的上下文继续执行
await DoSomethingAsync().ConfigureAwait(false);
//.... 这里开始在新的线程中运行

ConfigureAwait 配置 Taskawaiter,将延续任务封装回原始上下文,则为True ,否则为 False

详情可查阅ConfigureAwait(false)资料,这里暂时不做赘述。可阅读以下文章

  • 原文ConfigureAwait FAQ

    https://devblogs.microsoft.com/dotnet/configureawait-faq/

  • 译文理解C#中的ConfigureAwait

    https://www.cnblogs.com/xiaoxiaotank/p/13529413.html

异步方法异常:

异步方法异常时会返回在 Task 对象中,并将这个 Task 对象的状态改变为“已完成”。当 await 调用该 Task 对象时,await 会获得并(重新)抛出该异常,并保留原始的栈轨迹。

注意:

异步方法避免使用 Task.WaitTask<T>.Result ,因为他们会导致死锁。

示例:

public async Task<int> GetUrlContentLengthAsync()
{var client = new HttpClient();//异步执行请求,立即返回一个Task<string>,并将控制权让出Task<string> getStringTask =client.GetStringAsync("https://docs.microsoft.com/dotnet");//由于异步方法未执行等待,所以可以继续执行不依赖异步返回结果的同步方法DoIndependentWork();//挂起任务进度,并将控制权交割GetUrlContentLengthAsync方法的调用方,并返回一个Task<int>给调用方。//该任务表示将返回下载字符串长度的一个承诺//然后调用方会继续执行,执行不依赖于GetUrlContentLengthAsync返回结果的其它工作,否则就等待。string contents = await getStringTask;return contents.Length;
}void DoIndependentWork()
{Console.WriteLine("Working...");
}

await 运算符会暂停 GetUrlContentLengthAsync 方法:

  • getStringTask 完成之前,GetUrlContentLengthAsync 无法继续。

  • 同时,控件返回至 GetUrlContentLengthAsync 的调用方。

  • getStringTask 完成时,控件将在此继续。

  • 然后,await 会从 getStringTask 检索 string 结果

如果 DoIndependentWork 依赖于异步执行的结果,则在等待 getStringTask 返回结果期间不能进行任何工作。需要改成以下写法。

string getStringTask = await client.GetStringAsync("https://docs.microsoft.com/dotnet");

构成异步方法的条件:

  1. 方法签名要包含 async 修饰符。

  2. 按照约定,异步方法的名称以“Async”后缀结尾。

  3. 返回类型为以下类型之一

    1. 如果你的方法有返回值,则返回 Task<Result> 的类型。

    2. 如果你的方法没有返回值,则返回 Task 类型

  4. 方法中至少要包含一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。同时,并且将控制权返回到方法的调用方。

返回类型

await 运算符的操作数通常是以下几种.NET类型:Task、Task<TResult>、ValueTask或VauleTask<TResult>。但是任何可等待表达式都可以是await运算符的操作数。

总结

  1. 异步可以提高响应能力。

  2. 异步不会阻塞线程

  3. 使用 async 来标记异步方法

  4. 使用 await 来指定暂停点,挂起其进度,在等待的异步过程完成后才能继续通过该点。同时,会将控制权返回至异步方法的调用方,调用方可以继续执行不依赖于异步返回结果的其它工作。

  5. 如果使用了 Async 最好一直使用它

  6. 异步方法避免使用 Task.WaitTask<T>.Result ,因为他们会导致死锁。

.NET 中 async 和 await相关推荐

  1. C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  2. 【转载】 C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  3. Async和Await如何简化异步编程几个实例

    引言 C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就具体看看编译器到底在背后帮我们做了哪些复杂的工作的. 同步代码存 ...

  4. C# async 和 await 理解

    先假设如下场景: 主函数 Main,循环等待用户输入: 计算函数 Cal,耗时计算大量数据: class Test {static int Main(string[] args){while(true ...

  5. node mysql await_node.js中对 mysql 进行增删改查等操作和async,await处理

    要对mysql进行操作,我们需要安装一个mysql的库. 一.安装mysql库 npm install mysql --save 二.对mysql进行简单查询操作 const mysql = requ ...

  6. C# 5.0中引入了async 和 await

    C# 5.0中引入了async 和 await.这两个关键字可以让你更方便的写出异步代码. 看个例子: [csharp] view plaincopy public class MyClass { p ...

  7. ES6中的promise、async、await用法详解

    <!DOCTYPE html> <html> <head><title>Promise.async.await</title> </h ...

  8. 关于C#中async/await中的异常处理(上)

    关于C#中async/await中的异常处理(上) 参考文章: (1)关于C#中async/await中的异常处理(上) (2)https://www.cnblogs.com/sunjie9606/p ...

  9. node.js中对 mysql 进行增删改查等操作和async,await处理

    要对mysql进行操作,我们需要安装一个mysql的库. 一.安装mysql库 npm install mysql --save 二.对mysql进行简单查询操作 const mysql = requ ...

最新文章

  1. 开源社区的危机:拒绝被“白嫖”?2大著名项目遭作者破坏
  2. Postgresql创建只读用户,并开放部分表的权限
  3. inflate简介,LayoutInflater和inflate()方法的用法
  4. Fedora/Redhat 在线安装更新软件包,yum 篇 ── 给新手指南 (转载)
  5. C++ 比较两个字符串的“大小”
  6. AndroidStudio_Gradle介绍以及在androidstudio中的使用---Android原生开发工作笔记76
  7. Gitlab+jenkins持续集成+自动化部署(三)
  8. pytorch 生成随机数Tensor的方法 torch.rand torch.randn torch.normal torch.linespace
  9. linux命令文本处理(一)grep
  10. 学习笔记五:xss.tv通关笔记
  11. php 不恒等,php运算符==怎么使用以及与===恒等的区别是什么?
  12. [原创摄影]西藏行(一)从不同角度看布达拉
  13. 初中英语知识水平测试软件,美国初中生英文水平测试!百个单词检测,看看你认识几个...
  14. 搞独立运动,万人如海一身藏
  15. javase printwriter 打印流
  16. 锂离子电池性能测试软件,锂离子电池最常用的性能测试-放电曲线分析攻略(8000字长文)...
  17. [Bash]LeetCode195. 第十行 | Tenth Line
  18. eclipse常用插件在线安装地址或下载地址
  19. 苹果M1芯片和酷睿i9哪个更好
  20. MinHash (最小哈希)

热门文章

  1. 分布式锁的几种实现原理
  2. Unity中Instantiate一个prefab时需要注意的问题
  3. Java的原始数据类型一共就8个
  4. sql语句查询结果合并union 和union all用法
  5. OnIntialDialog() (Dialog应用)和 OnIntialUpdate(View应用)的 程序起始点
  6. 养鹿专辑二:恋鹿篇之枕着老婆的梦编程
  7. 动态切换父元素隐藏和显示里面的子元素的动画会再一次执行吗?
  8. 亿方云CEO程远:转型第一式:链接企业人与数据
  9. python字符串格式化方法 format函数的使用
  10. 基于key/value+Hadoop HDFS 设计的存储系统的shell命令接口