关于async和await的一些误区实例详解
转载自 http://www.jb51.net/article/53399.htm
这篇文章主要介绍了关于async和await的一些误区实例详解,有助于更加深入的理解C#程序设计,需要的朋友可以参考下
微软官方的MSDN上说async和await是“异步”,但是不少人(包括笔者自己)都有一些误区需要澄清:为什么await语句之后没有执行?不是异步吗?
先举一个示例代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public partial class Form1 : Form{ public async Task Processing() { await Task.Delay(5000); label1.Text = "Succuessful"; } public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { await Processing(); MessageBox.Show("Button's event completed"); }} |
很多人(包括笔者)一开始会觉得异步好像类似多线程一样,到await的时候会在后台先开启一个线程执行任务,随后主线程(这里是UI线程)将自动执行后面的部分(即弹出“Button's event completed”的消息框)。
其实这个理解是错误的。async和await的本质其实是“yield return”和“LINQ”的“迭代式”等待。我们应该清楚一点:那就是你写了LINQ语句:
|
1
2
3
4
5
6
7
|
var results = from …… select ……;foreach(var r in results){ ……} |
当你下断点你会发觉results并不会立即执行,直到使用到results的地方(例子中也就是foreach这里)才会被执行(此时黄色跟踪调试的光棒又会折回到var results……这里,然后等到results执行完毕之后才真正进入foreach进行执行)。
所以,async/await和LINQ的这种“迭代式”的“异步操作”是异曲同工的。只不过async/await本质是返回一个Task而已,而Task又是异步的(因为Task本质就是一个线程),所以真正执行到(使用到async方法的时候)带有await的方法的时候,后台才会真正开启一个线程去执行任务。此时主线程会等待这个Task线程直到其执行完毕(IsComplete属性为True为止)。所以界面是不会卡顿的。
所以,await是Task的异步等待而已,并不是我们所谓的“异步操作”;拿它和LINQ作对比,你会发现LINQ执行顺序和它一致,只不过LINQ没有异步等待(当然没有!又没有开启线程啥的……)。
我们进一步可以这样对比:
LINQ:变量 = LINQ语句(表达式)
等到使用LINQ变量的时候才折返到LINQ语句处真正执行LINQ语句。
异步等待:变量 = 异步方法
等到使用await+异步方法的时候才会折返到该异步方法处,开启线程真正执行异步方法,主线程被挂起(但不会造成界面死掉),直至子线程Task任务完全执行完毕为止。
在LINQ中,你如果需要立即执行,可以使用扩展方法:
var results = (from ……
select ……).ToList();
因为立即使用到了这个LINQ语句,所以会被立即执行。
同样地,异步等待也可以变成类似Wait一样的同步等待:
|
1
2
3
4
5
|
private async void button1_Click(object sender, EventArgs e){ Processing().GetAwaiter().GetResult(); MessageBox.Show("Button's event completed");} |
因为Processing本来就返回Task,当然也可以使用Wait进行同步等待。
关于async和await的一些误区实例详解的更多相关文章
- linux基础-磁盘阵列(RAID)实例详解
磁盘阵列(RAID)实例详解 raid技术分类 软raid技术 硬raid技术 Raid和lvm的区别 为什么选择用raid RAID详解 RAID-0 RAID-1 RAID-5 Raid-10 R ...
- Cocos2d-x 3.X手游开发实例详解
Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...
- JavaScript学习笔记-实例详解-类(二)
实例详解-类(二) //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...
- JavaScript学习笔记-实例详解-类(一)
实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ...
- Entity Framework实例详解
Entity Framework Code First的默认行为是使用一系列约定将POCO类映射到表.然而,有时候,不能也不想遵循这些约定,那就需要重写它们.重写默认约定有两种方式:Data Anno ...
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)
最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...
- Linux下rz命令使用的实例详解
Linux中rz命令和sz命令都可用于文件传输,而rz命令主要用于文件的上传,下面将通过几个实例来给大家详细介绍下Linux下rz命令的用法,一起来学习下吧. rz命令可以批量上传文件,当然也可上传单 ...
- 实例详解 DB2 排序监控和调优
实例详解 DB2 排序监控和调优http://automationqa.com/forum.php?mod=viewthread&tid=2882&fromuid=2
- 转:【工欲善其事必先利其器】—Entity Framework实例详解
开始本篇文章之前,先说一下Entity Framework 6 Alpha1在NuGet中已可用,原文链接http://blogs.msdn.com/b/adonet/archive/2012/10/ ...
随机推荐
- 题目1043:Day of Week(输入日期与当前日起天数差%7,在做相关星期调整)
题目描述: We now use the Gregorian style of dating in Russia. The leap years are years with number divis ...
- JavaScript:子ウィンドウから親ウィンドウを再読み込みさせる方法
ことの起こり Webの画面では.新規入力をしようとすると.別ウィンドウ=子ウィンドウが開いて入力し.登録ボタンを押すと.子ウィンドウが閉じる仕組みがある. 子ウィンドウが閉じるだけなら問題ないが.一覧 ...
- svn文件清理Bat脚本
@echo On@Rem C:\Users\caoxiancc\Desktop\Ueditor-thinkphp-master\Ueditor --svn跟路径@PROMPT [Com] @for / ...
- MySQL 字段类型详解
一.非数字类型 类型 范围 说明 Char(N) [ binary] N=1~255 个字元 binary :分辨大小写 固定长度 std_name cahr(32) not null VarCh ...
- 问题-关于SizeOf在Delphi7和Delphi2009下结果分别是16/32
问题:同样的代码在Delphi7和Delphi2009下结果分别是16/32,为什么?var LWindCode : array [0..15] of char; begin showmess ...
- RegExp.exec
来自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec Summ ...
- 如何使用Keil仿真环境查看CPU类型字长?【worldsing笔记】
笔者上次写了如何用IAR查CPU的字长和数据类长度的方法:点击这里查看 今天试着在Keil MDK 5.0 里查看CPU的字长和数据类长度,打开一个已有的工程,编译并进入Debug,如图1.1所示: ...
- C++学习笔记(十四):模板
模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性.模版可以分为两类,一个是函数模版,另外一个是类模版.Java中对应的技术称为泛型. 函数模板 ...
- Modernizr 与 Polyfill
之前提到,Modernizr 是 HTML5 和 CSS3 的特性检测工具,这里简单介绍一下它的用法.最简单的用法是在页面的 <head> 中添加 Modernizr 的 JavaScri ...
- jdbc连接的工具类
在不实用框架的情况下,有一个jdbc的工具类来进行数据库的连接就再好不过了,下面提供这个工具类DBUtil.java package org.jdbc.test; import java.io.Inp ...