谈到C#中的异步编程,离不开Async和Await关键字

谈到异步编程,首先我们就要明白到底什么是异步编程。 平时我们的编程一般都是同步编程,所谓同步编程的意思,和我们平时说的同时做几件事情完全不同。 在计算机的世界里,同步编程的意思说 按照顺序来执行,或者说是 一个接着一个地有序的来执行, 比如目前我们在代码中有三件任务来执行,那么必须先执行完第1件,再执行第2件,接下来再执行第3件。 在这个过程中,第1件没有完成,你是没法开始做第2件事情的,必须等待。

比如一个人烧开水需要10分钟,5分钟找杯子,5分钟找茶叶。 这件事情在同步编程的世界里需要20分钟完成,因为必须先烧开水10分钟,等烧完开水后。 才开始做第2件事情找杯子,花费5分钟。 找完杯子后,才开始做第3件事情-找茶叶,又花费5分钟。这样,整个过程就花费了20分钟。但其实这3件事情可以同时做,互相并不影响,这就是异步编程的概念了

由上面这个例子中可以发现,在计算机编程世界里,【异步编程】才是真正的同时进行事情,而【同步编程】是一件一件的有序执行。 上面的例子,如果采用异步编程,那么10分钟就可以全部完成。

在C#中,异步编程中有三个方面需要注意:

1.为了表示一个方法是异步方法,需要使用async关键字来修饰该方法签名

2. 异步方法的返回值类型 --- 只有 void, Task 和 Task<T>

3. 在异步方法内部,你需要使用await关键字来修饰一个可以等待的【可等待】类型,来实现异步

我们通过例子来比较同步编程和异步编程的不同

举例:  比如页面上有个【计算】按钮,点击该按钮 程序将会进行一个复杂运算,该运算将花费45秒的时间,运算完后返回计算结果,现实在页面的一个textbox文本框里面

private void btnCalculate_Click(object sender, EventArgs e)
{
int calResult = ToCalculate();
this. Textbox1.Text = calResult; } private int ToCalculate()
{
// 这里有复杂的计算过程,将耗时45秒, 我们这里通过让线程休眠45秒钟来模拟
System.Threading.Thread.Sleep(); return ; }

在上面代码中,我们假设方法ToCalculate方法要进行复杂的计算。在这里,我们通过让当前线程挂起45秒,来模拟耗时45秒的复杂计算过程.

我们可以想象得到,上面得代码中,当用户在界面上点击btnCalculate按钮时,UI在接下来的45秒里将毫无反应,程序将只干一件事情,就是允许ToCalculate方法来进行耗时45秒的复杂计算。45秒之后,才会把计算结果返回到Textbox1中,再接下来做其他的操作

这个显然非常的用户不友好,因为用户会发现他需要等在那里45秒,什么事情也不能干。如果在这个等待过程中,用户在UI上还能同时操作干其他的事情呢?  这个就需要涉及到异步编程的概念

【异步编程】的操作过程如下:

执行异步方法,当遇到await关键字时,表示要开始执行一个异步方法,await关键字来修饰的方法是一个方法。这个时候程序会做两件事情

第1件: 程序去执行await关键字修饰的异步方法

第2件: 在做第1件的同时,把控制权立即返回给调用者,也就是说调用者这个时候,可以在等待异步方法执行的过程中,同时去做其他事情,因为控制权已经在它手中了。

看看上面的例子,如果采用异步方法,当用户在界面上点击btnCalculate按钮时,程序会执行异步方法ToCalculate. 但与此同时,控制权也马上回到UI手上,也就是说在后台进行耗时45秒的复杂计算的同时,用户可以同时在UI上进行其他操作。当异步计算结束,把计算结果显示在UI的Textbox1上。

了解了整个过程后,我们使用异步方法来改写上面的代码

private async void btnCalculate_Click(object sender, EventArgs e)
{
int calResult = await ToCalculate();
this. Textbox1.Text = calResult;
} private Task<int> ToCalculate()
{
//将复杂计算的过程放入一个Task<int>中,新开线程
var t = Task.Run(()=>
{
System.Threading.Thread.Sleep();
return ;
});
//返回的是这个Task<int>
return t;
}

从上面的代码变动中,我们可以看到几处变动情况

1. 在方法的签名中,在public后面加入了async关键字, 将该方法标识成一个异步方法。 这样,让程序知道这个方法是一个异步方法, 此时它内部的await才会被认为是一个关键字。

或者说,如果在方法的签名中没有async关键字, await会被认为是一个普通的变量名,也就是说,它会被当成普通的C#标识符来处理(类似于 string await ="test";)

2. 在async标识的异步方法中,在需要异步调用的方法ToCalculate方法前面,使用await关键字

3. 异步调用的方法ToCalculate,只能是三种返回值类型中的一种void, Task 和 Task<T>。 在这个例子中,是Task<T>

 

C#中的异步编程Async 和 Await的更多相关文章

  1. .NET4.5 异步编程 async和await

    msdn介绍:https://msdn.microsoft.com/zh-cn/library/hh191443.aspx 其实很简单,标记了async的方法为异步方法,从方法的左大括号开始同步执行, ...

  2. C#异步编程(async and await)及异步方法同步调用

    1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库=异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方 ...

  3. 异步编程- async和await

    使用目的 避免阻塞主线程 提高程序响应能力 C#中使用 C# 中的 Async 和 Await 关键字是异步编程的核心. 疑惑 The async and await keywords don't c ...

  4. .net异步编程async和await的讨论收获

    微软官方描述: C# 5 引入了一种简便方法,即异步编程.此方法利用了 .NET Framework 4.5 及更高版本..NET Core 和 Windows 运行时中的异步支持. 编译器可执行开发 ...

  5. 彻底搞懂C#异步编程 async和await的原理

    1.前提 熟练掌握Task并行编程. 2.用Task并行解释async和await异步 因为控制台有多线程操作的优化,因此这里选择winform来做示例. 测试代码如下所示: 有三个textbox,一 ...

  6. C#异步编程----async和await组合的写法

    微软示例: private async void StartButton_Click(object sender, RoutedEventArgs e) { // ExampleMethodAsync ...

  7. 异步编程Async/await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

  8. .net 异步编程async & await关键字的思考

    C# 5.0引入了两个关键字 async和await,这两个关键字在很大程度上帮助我们简化了异步编程的实现代码,而且TPL中的task与async和await有很大的关系 思考了一下异步编程中的asy ...

  9. 反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑) C#中缓存的使用 C#操作redis WPF 控件库——可拖动选项卡的TabControl 【Bootstrap系列】详解Bootstrap-table AutoFac event 和delegate的分别 常见的异步方式async 和 await C# Task用法 c#源码的执行过程

    反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑)   背景介绍: 为了平衡社区成员的贡献和索取,一起帮引入了帮帮币.当用户积分(帮帮点)达到一定数额之后,就会“掉落”一定数量的“帮帮 ...

随机推荐

  1. js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动)

    本文为大家详细介绍下使用js实现遮罩弹出层居中,且随浏览器窗口滚动条滚动,示例代码如下,感兴趣的朋友可以参考下, js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动) 下面看看我的原始代码: & ...

  2. iis部署网页时应该避免的特殊端口

    1 tcpmux 7 echo 9 discard 11 systat 13 daytime 15 netstat 17 qotd 19 chargen 20 ftp data 21 ftp cont ...

  3. 关于 webpack-dev-server 热更新出现重复的问题

    关于 webpack-dev-server 热更新出现重复的问题 webpack-dev-server 在前端开发时很方便,可以热更新,只需要配置 webpack.config.js 即可. 但是昨天 ...

  4. Tomcat服务器下 catalina.out 日志开关

    很多异常在 debug 日志里不会打印,但在 catalina.out 里会打印,比如方法调用找不到,jdk 版本不匹配等.但是打开了该日志开关又会产生一个问题,就是它会哗啦啦的不断急剧膨胀,文件太大 ...

  5. sql for 存储过程格式

    sql DELIMITER && CREATE PROCEDURE test2() BEGIN DECLARE i INT; ; DO ')); ; END WHILE; END; & ...

  6. 半导体巨头青睐物联网领域 众强联手打造MCU生态系统

    随着万物互联的时代到来,众多半导体巨头纷纷转战物联网领域.早在十年前,意法半导体曾将STM32推向市场,意法半导体对32位MCU在物联网方面的应用在两年前就已展开攻势. 4月25日,历经两届盛况的ST ...

  7. 【转】jmeter实践

    目录(?)[-] Jmeter相关概念简介 应用实例 AbApacheBench对比 本文主要介绍性能测试中的常用工具jmeter的使用方式,以方便开发人员在自测过程中就能自己动手对系统进行自动压测和 ...

  8. juc原子类之二:基本类型原子类AtomicInteger(AtomicLong、AtomicBoolean)

    一.AtomicInteger简介 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.以AtomicInteger对基本类型的原子类 ...

  9. PL/SQL 训练12--动态sql和绑定变量

    --什么是动态SQL?动态PL/SQL--动态SQL是指在运行时刻才构建执行的SQL语句--动态PL/SQL是指整个PL/SQL代码块都是动态构建,然后再编译执行 --动态SQL来可以用来干什么? - ...

  10. Oracle 2套rac集群指向单机多实例的复制搭建

    Oracle 2套rac集群指向单机多实例的复制搭建 由于环境限制,现在需要把2套rac集群通过dg复制指向远端的单机多实例上面. rac指向第一个实例的前面已经有文档 这里直接添加第二个实例的复制搭 ...