目录
- 异步编程的简介
- 异步提高响应能力
- 更容易编写的异步方法
- 异步方法的控制流(核心)
- 异步中的线程
- async 和 await 修饰符
- 返回类型和参数信息
- 命名的约定
一、异步编程的简介
通过使用异步编程,你可以避免性能瓶颈并增强你的应用程序的总体响应能力。
因此,我们仅需要进行一小部分编程的工作就可以获得异步编程的所有优点。
二、异步提高响应能力
在使用异步的过程中,我们的应用程序可继续执行不依赖 Web 资源的其他工作,并会一直等待阻塞的任务顺利完成。
这是一些典型的使用异步的应用场景,以及一些在 .NET >= 4.5 后新增的类库。
所有与用户界面相关的操作通常共享一个线程,所以使用异步对于使用 UI 线程的 App 来说是非常重要的。
如果说你的 App 所有操作都是同步的,也就是说,当一个线程出现阻塞,其它线程都会出现阻塞,更严重的是, App 会停止响应。
三、更容易编写的异步方法
示例:
/// <summary> /// 异步访问 Web /// </summary> /// <returns></returns> /// <remarks> /// 方法签名的 3 要素: /// ① async 修饰符 /// ② 返回类型 Task 或 Task<TResult>:这里的 Task<int> 表示 return 语句返回 int 类型 /// ③ 方法名以 Async 结尾 /// </remarks> async Task<int> AccessTheWebAsync() { //记得 using System.Net.Http 哦 var client = new HttpClient(); //执行异步方法 GetStringAsync Task<string> getStringTask = client.GetStringAsync("http://www.google.com.hk/"); //假设在这里执行一些非异步的操作 Do(); //等待操作挂起方法 AccessTheWebAsync //直到 getStringTask 完成,AccessTheWebAsync 方法才会继续执行 //同时,控制将返回到 AccessTheWebAsync 方法的调用方 //直到 getStringTask 完成后,将在这里恢复控制。 //然后从 getStringTask 拿到字符串结果 string urlContents = await getStringTask; //返回字符串的长度(int 类型) return urlContents.Length; }
如果 AccessTheWebAsync 在调用 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 传输至线程池的工作区分开来。
static async Task<Guid> Method1Async() //Task<Guid> { var result = Guid.NewGuid(); await Task.Delay(1); //这里返回一个 Guid 的类型 return result; } static async Task Method2Async() //Task { //Do... await Task.Delay(1); //Do... //这里没有 return 语句 }
//调用 Method1Async //方式一 Task<Guid> t1 = Method1Async(); Guid guid1 = t1.Result; //方式二 Guid guid2 = await Method1Async(); //调用 Method2Async //方式一 Task t2 = Method2Async(); await t2; //方式二 await Method2Async();
任务可封装有关异步进程状态的信息,如果未成功,则最后会封装来自进程的最终结果,或者是由该进程引发的异常。
【疑问】那么 void 返回类型是在什么情况下才使用的呢?
异步事件处理程序通常作为异步程序的起始点。void 返回类型告诉了编译器,无需对他进行等待,并且,对于 void 返回类型的方法,我们也无法对他进行异常的捕捉。
异步方法不能够在参数中声明与使用 ref 和 out 关键字,但是异步方法可以调用包含这些参数的方法。