【博主】反骨仔 【出处】http://www.cnblogs.com/liqingwen/p/5922573.html
目录
一、异步编程的简介
通过使用异步编程,你可以避免性能瓶颈并增强你的应用程序的总体响应能力。
因此,我们仅需要进行一小部分编程的工作就可以获得异步编程的所有优点。
二、异步提高响应能力
在使用异步的过程中,我们的应用程序可继续执行不依赖 Web 资源的其他工作,并会一直等待阻塞的任务顺利完成。
这是一些典型的使用异步的应用场景,以及一些在 .NET >= 4.5 后新增的类库。
所有与用户界面相关的操作通常共享一个线程,所以使用异步对于使用 UI 线程的 App 来说是非常重要的。
如果说你的 App 所有操作都是同步的,也就是说,当一个线程出现阻塞,其它线程都会出现阻塞,更严重的是, App 会停止响应。
三、更容易编写的异步方法
1 /// <summary> 2 /// 异步访问 Web 3 /// </summary> 4 /// <returns></returns> 5 /// <remarks> 6 /// 方法签名的 3 要素: 7 /// ① async 修饰符 8 /// ② 返回类型 Task 或 Task<TResult>:这里的 Task<int> 表示 return 语句返回 int 类型 9 /// ③ 方法名以 Async 结尾 10 /// </remarks> 11 async Task<int> AccessTheWebAsync() 12 { 13 //记得 using System.Net.Http 哦 14 var client = new HttpClient(); 15 16 //执行异步方法 GetStringAsync 17 Task<string> getStringTask = client.GetStringAsync("http://www.google.com.hk/"); 18 19 //假设在这里执行一些非异步的操作 20 Do(); 21 22 //等待操作挂起方法 AccessTheWebAsync 23 //直到 getStringTask 完成,AccessTheWebAsync 方法才会继续执行 24 //同时,控制将返回到 AccessTheWebAsync 方法的调用方 25 //直到 getStringTask 完成后,将在这里恢复控制。 26 //然后从 getStringTask 拿到字符串结果 27 string urlContents = await getStringTask; 28 29 //返回字符串的长度(int 类型) 30 return urlContents.Length; 31 }
GetStringAsync() 时没有其它操作(如:代码中的 Do()),你可以用这样的方式来简化代码。
string urlContents = await client.GetStringAsync("http://www.google.com.hk/");
简单总结:
async 修饰符。
(2)根据约定,异步方法的名称需要以“Async”后缀为结尾。
(3)3 种返回类型:
① Task<TResult>:返回 TResult 类型。
② Task:没有返回值,即返回值为 void。
③ void:只适用于异步事件处理程序。
(核心)
步骤解析:
AccessTheWebAsync() 异步方法。
② AccessTheWebAsync 创建 HttpClient 对象并调用它的 GetStringAsync 异步方法来下载网站内容。
GetStringAsync 的正在进行的进程,其中承诺当工作完成时产生实际字符串值。
DoIndependentWork 的调用表示。
⑤ DoIndependentWork 是完成其工作并返回其调用方的同步方法。
该任务表示对产生下载字符串长度的整数结果的一个承诺。
GetStringAsync。
urlContents。
在异步方法最终完成其工作时,任务会标记为已完成,而结果(如果有)将存储在任务中。
可以使用 Task.Run 将占用大量 CPU 的工作移到后台线程,但是后台线程不会帮助正在等待结果的进程变为可用状态。
Task.Run 传输至线程池的工作区分开来。
-
finally 块中的将不会执行。
-
异步方法中通常包含一个或多个 await 运算符,当然,一个 await 表达式都不存在也不会导致编译器错误,但是编译器会发出警告,该方法在执行的时候依然会依照同步方法来执行,async 其实只是一个标识的作用而已,告诉编译器他“应该”是一个异步方法。
示例:
1 static async Task<Guid> Method1Async() //Task<Guid> 2 { 3 var result = Guid.NewGuid(); 4 5 await Task.Delay(1); 6 7 //这里返回一个 Guid 的类型 8 return result; 9 } 10 11 static async Task Method2Async() //Task 12 { 13 //Do... 14 15 await Task.Delay(1); 16 17 //Do... 18 19 //这里没有 return 语句 20 }
1 //调用 Method1Async 2 //方式一 3 Task<Guid> t1 = Method1Async(); 4 Guid guid1 = t1.Result; 5 6 //方式二 7 Guid guid2 = await Method1Async(); 8 9 //调用 Method2Async 10 //方式一 11 Task t2 = Method2Async(); 12 await t2; 13 14 //方式二 15 await Method2Async();
任务可封装有关异步进程状态的信息,如果未成功,则最后会封装来自进程的最终结果,或者是由该进程引发的异常。
【疑问】那么 void 返回类型是在什么情况下才使用的呢?
异步事件处理程序通常作为异步程序的起始点。void 返回类型告诉了编译器,无需对他进行等待,并且,对于 void 返回类型的方法,我们也无法对他进行异常的捕捉。
异步方法不能够在参数中声明与使用 ref 和 out 关键字,但是异步方法可以调用包含这些参数的方法。
传送门
【参考引用】微软官方文档图片
【参考】https://msdn.microsoft.com/zh-cn/library/windows/apps/hh191443(v=vs.110).aspx