Asycn/Await 异步编程初窥
经过两天密集型的学习,翻阅了大量 webpages ,点击了不少重点 blogs,总算基本了解了一些 async/await 搭配使用的入门技巧,总结一下
1. async/await 应该只是语法上的甜点,让想使用异步方法运行程序的程序员能够专心专注代码逻辑,而别被原来的 Begin... End... 型或是IAsync ...Async 的老式异步带的越来越远。想起刚试着编写 Tcp Listener的时候,真是噩梦。异步响应必须放在另一个回调方法或是事件中,而从异步响应产生的异步接收又必须再次放到另一个回调方法或是事件中,更可怕的是,如何循环它们。
2. async/await 标识的方法,“本身不主动创建额外线程”——这句话很容易让人误解。《Async 和 Await 异步编程的原理》这篇文章写的比较详细,异步,必然多线程,更何况是从 UI 线程启动的。只是这种多线程被Framework透明掉了,使用者不必自己在这方面去走脑子怎么创建线程,怎么回收,怎么捕捉异常,还得让代码好看一点。
3. await 让我开始的时候陷入了一个误区,认为使用 var result = await FunRun(...) 这种写法,FunRun()方法就会异步运行而不会阻塞UI线程,这是错的,我忽略了一个很严重的问题。先看一下原来错误的代码:
private async Task<TimeSpan> Download(Uri address, string fileName)
{
this.uri = address;
this.fileName = fileName;
DateTime start = DateTime.Now;
//
HttpWebRequest request;
HttpWebResponse response = null;
try
{
request = (HttpWebRequest)WebRequest.Create(address);
response = (HttpWebResponse)request.GetResponse();
using (Stream httpStream = response.GetResponseStream())
{
using (FileStream writer = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))
{
byte[] buffer = new byte[];
int readLength = httpStream.Read(buffer, , buffer.Length);
//
while (readLength > )
{
writer.Write(buffer, , readLength);
readLength = httpStream.Read(buffer, , buffer.Length);
}
}
}
}
catch(Exception)
{
if (response != null) { response.Close(); }
} return DateTime.Now - start;
}
代码完成下载一个资源到指定位置的功能,本身逻辑没有错误,看起来这似乎是一个标准的带有 async 标记和 Task<T> 返回类型的方法,所以我信心慢慢的调用了它。
private async void button1_Click(object sender, EventArgs e)
{
//略过部分逻辑判断的东西
...... TestApp.HttpDownloader.HttpDownloaderEngine hdEngine = new HttpDownloaderEngine();
var time = await hdEngine.Download(address, saveFileTextBox.Text);
MessageBox.Show(string.Format("下载完成,共耗时 {0} 秒", time.Seconds.ToString()));
}
调用错误写法的方法
Button1 的 Click 事件本身也没有问题,我还细心的加上了 async 标记(当然,不加也不让我过去啊),一切很好我即刻运行,结果让我很困惑,的确成功的下载了 Mp3 到我的电脑,可不管时间长短,我的 UI 依旧像同步的一样,不能响应知道执行完成。问题处在哪里?
人是需要休息的,学习->休息->消化,经过再次梳理和查看资料,我找出了第 3 点开头我说的,Bug 在于 HttpDownloadEngine 的 Download 方法我虽然标记了 async,button_click 误以为 Download 方法可以完成异步工作,button_click 是没错的,错在 Download 方法内不,没有任何“异步执行的代码”!也就是说,Download 方法内没有出现一个 await ,这使得标记了 async 的 Download 方法依旧是同步的,button_click 调用了一个同步方法在同步执行。
如何修改呢,在 Download 方法内的关键处执行 await Task<T> ....Async ,如 readLength = await responseStream.ReadAsync(buffer, 0, buffer.Length);,关键处是指的确需要异步执行的地方。
4. 我要感谢 Microsoft,我不是大神,我是个爱好者,是微软借鉴并创造了 .Net 和无与伦比的 VS,让我和像我一样的人都能领略计算机的更多魅力,这种魅力,来自于创造和分享给他人。
贴上一个下载的结果图

Asycn/Await 异步编程初窥的更多相关文章
- Asycn/Await 异步编程初窥(二)
经过总过4天的学习和实践,做完了 WinForm 下 .Net 4.5 的基本异步应用,实现了一个 Http 协议下载的测试程序,为以后使用 .Net 4.5 积累知识和经验.这个小程序完成这样几个作 ...
- Asycn/Await 异步编程
Asycn/Await 异步编程初窥(二) 经过总过4天的学习和实践,做完了 WinForm 下 .Net 4.5 的基本异步应用,实现了一个 Http 协议下载的测试程序,为以后使用 .Net ...
- Async和Await异步编程的原理
1. 简介 从4.0版本开始.NET引入并行编程库,用户能够通过这个库快捷的开发并行计算和并行任务处理的程序.在4.5版本中.NET又引入了Async和Await两个新的关键字,在语言层面对并行编程给 ...
- async And await异步编程活用基础
原文:async And await异步编程活用基础 好久没写博客了,时隔5个月,奉上一篇精心准备的文章,希望大家能有所收获,对async 和 await 的理解有更深一层的理解. async 和 a ...
- 【转】C# Async/Await 异步编程中的最佳做法
Async/Await 异步编程中的最佳做法 Stephen Cleary 近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支 ...
- 李洪强iOS开发之函数式 编程初窥
函数式 编程初窥 最近在学习Erlang和Python.Erlang是完全的函数式编程语言,Python语言是面向对象的语言,但是它的语法引入了大量的函数式编程思想.越研究越觉得函数式的编程思路可 ...
- .NET Web应用中为什么要使用async/await异步编程
前言 什么是async/await? await和async是.NET Framework4.5框架.C#5.0语法里面出现的技术,目的是用于简化异步编程模型. async和await的关系? asy ...
- C#中 Thread,Task,Async/Await 异步编程
什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调 ...
- async/await 异步编程(转载)
转载地址:http://www.cnblogs.com/teroy/p/4015461.html 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入 ...
随机推荐
- 利用缓存、Timer间隔时间发送微信的实例,很有用的例子
//Class WechatOfferExcutor 此类为微信触发类,属于上层调用类,其中有用到用静态变量缓存offer信息,Task异步执行发送方法等 using Newtonsoft.Json. ...
- 前端学习笔记(zepto或jquery)—— 布局技巧(一)
html5中有一些标签我们很难改变其样式,例如input=file,select等.这个时候我们需要改变一下思路,将原有透明度置为0,借助于div或span等以控制样式的标签来代替. 效果图: < ...
- 使用ArcGIS API for Silverlight 进行复合多条件空间查询
原文:使用ArcGIS API for Silverlight 进行复合多条件空间查询 这两天帮网上认识的一个兄弟做了一个查询的示例,多多少少总结一下,在此和大家分享. 为什么说是复合多条件呢?因为进 ...
- AIX加入能telnet远程连接方法的帐户
AIX 加入该账户可以使用命令mkuser 和 SMIT 两种方法,这里有SMIT方式 1.采用root 帐户登录AIX 2.输入 smitty user 3.选择Add a User 4.输入&qu ...
- Asp.net MVC + EF + Spring.Net 项目实践(目录)
用4篇博客来搭一个MVC的框架,可能对初学者会有一些帮助,大家共勉吧.我觉得对于中小型项目,这个框架可能还是有一定的用处的,希望能够帮助到一些人. Asp.net MVC + EF + Spring. ...
- HDU5014Number Sequence(贪心)
HDU5014Number Sequence(贪心) 题目链接 题目大意: 给出n,然后给出一个数字串,长度为n + 1, 范围在[0, n - 1].然后要求你找出另外一个序列B,满足上述的要求,而 ...
- 使用jquery实现放大镜效果
原文:使用jquery实现放大镜效果 实现原理 首先,我们讲解一下放大镜效果的实现方式: 方法一:准备一张高像素的大图,当鼠标放到原图上,加载显示大图的对应位置. 方法二:对原图片进行放大,也就是调整 ...
- 如何判断微信内置浏览器(通过User Agent实现)
在进行微信公众账号开发的时候,其中很大一块是微站点的开发,我们需要知道当前的浏览器是微信内置的浏览器,那么如何判断呢? 微信内置浏览器的 User Agent 如何判断微信内置浏览器,首先需要获取微信 ...
- C#中使用REDIS
C#中使用REDIS 上一篇>> 摘要 上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis.本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# ...
- Oracle 11g for Windows 简体中文版的安装过程
原文:Oracle 11g for Windows 简体中文版的安装过程 我的配置 操作系统:Windows Server 2003 sp2 内存:1024M以上 1.下载Oracle 11g 地址 ...