经过两天密集型的学习,翻阅了大量 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 异步编程初窥的更多相关文章

  1. Asycn/Await 异步编程初窥(二)

    经过总过4天的学习和实践,做完了 WinForm 下 .Net 4.5 的基本异步应用,实现了一个 Http 协议下载的测试程序,为以后使用 .Net 4.5 积累知识和经验.这个小程序完成这样几个作 ...

  2. Asycn/Await 异步编程

    Asycn/Await 异步编程初窥(二)   经过总过4天的学习和实践,做完了 WinForm 下 .Net 4.5 的基本异步应用,实现了一个 Http 协议下载的测试程序,为以后使用 .Net ...

  3. Async和Await异步编程的原理

    1. 简介 从4.0版本开始.NET引入并行编程库,用户能够通过这个库快捷的开发并行计算和并行任务处理的程序.在4.5版本中.NET又引入了Async和Await两个新的关键字,在语言层面对并行编程给 ...

  4. async And await异步编程活用基础

    原文:async And await异步编程活用基础 好久没写博客了,时隔5个月,奉上一篇精心准备的文章,希望大家能有所收获,对async 和 await 的理解有更深一层的理解. async 和 a ...

  5. 【转】C# Async/Await 异步编程中的最佳做法

    Async/Await 异步编程中的最佳做法 Stephen Cleary 近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支 ...

  6. 李洪强iOS开发之函数式 编程初窥

    函数式 编程初窥   最近在学习Erlang和Python.Erlang是完全的函数式编程语言,Python语言是面向对象的语言,但是它的语法引入了大量的函数式编程思想.越研究越觉得函数式的编程思路可 ...

  7. .NET Web应用中为什么要使用async/await异步编程

    前言 什么是async/await? await和async是.NET Framework4.5框架.C#5.0语法里面出现的技术,目的是用于简化异步编程模型. async和await的关系? asy ...

  8. C#中 Thread,Task,Async/Await 异步编程

    什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调 ...

  9. async/await 异步编程(转载)

    转载地址:http://www.cnblogs.com/teroy/p/4015461.html 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入 ...

随机推荐

  1. jQuery按回车键执行指定方法

    1.按Enter键执行指定方法: //按回车进入页面 $(function(){ $(document).keydown(function(event){ if (event.keyCode == 1 ...

  2. 最新HTML BroadcastChannel API引荐

    HTML BroadcastChannel API 当前浏览器中只有Firefox38唯一能支持BroadcastChannel API(在编写本文的时间点),而Firefox38官方宣称要到2015 ...

  3. 条形码(JBarcode)

    一世尘梦 少小离家老大回,妖娆尘世,程序唧唧:问君能有几多愁,恰是满屏BUG无处修. 商品条形码(JBarcode) 之前没有使用过这个,现在使用JBarcode生成商品条形码,工作之前的准备工作: ...

  4. C# 实现 Hyper-V 虚拟机 管理

    原文:C# 实现 Hyper-V 虚拟机 管理 Hyper-V WMI Provider 工具类如下: "; break; } return status; } } /// <summ ...

  5. WCF与Web API 区别

    WCF与Web API 区别(应用场景)   Web api  主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, ...

  6. FlexBuilder远程调试WEB应用

    Flex使用的开发工具FlexBuiler 3,web server使用apache. 1 第一次安装IE相应flashplayer的debug版本号,下载Flash player 11.8安装,下载 ...

  7. 对于GetBuffer() 与 ReleaseBuffer() 的一些分析

    先 转载一段别人的文章 CString类的这几个函数, 一直在用, 但总感觉理解的不够透彻, 不时还实用错的现象. 今天抽时间和Nico一起分析了一下, 算是拨开了云雾: GetBuffer和Rele ...

  8. JAVA学习课第五十三届 — IO流程(七)File打靶 &amp; Properties设置

    一个.锻炼 深度遍历目录 深度遍历非常自然而然想到递归,而递归就非常自然的想到事实上现的底层算法是栈 对指定文件夹下列出全部内容(包括子文件夹的内容) PS:建议不要遍历C盘 import java. ...

  9. Spring Resource之ResourceLoader

    ResourceLoader接口意味着任何实现的对象都能够返回Resource实例. public interface ResourceLoader { Resource getResource(St ...

  10. 自己编译的openwrt在开机时一直打印jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found...的错误提示

    具体的输入信息是这样的. uboot> http Link down: eth0 Ethernet mode (duplex/speed): / Mbps HTTP server is star ...