原创

C#async/await 结构

先解析一下专业名词:

同步方法:一个程序调用某个方法,等到其执行完成之后才进行下一步操作。这也是默认的形式。

异步方法:一个程序调用某个方法,在处理完成之前就返回该方法。通过 async/await 我们就可以实现这种类型的方法。

async/await 结构可分成三部分:

(1)调用方法:该方法调用异步方法,然后在异步方法执行其任务的时候继续执行;

(2)异步方法:该方法异步执行工作,然后立刻返回到调用方法;

(3)await 表达式:用于异步方法内部,指出需要异步执行的任务。一个异步方法可以包含多个 await 表达式(不存在 await 表达式的话 IDE 会发出警告)。

异步方法:在执行完成前立即返回调用方法,在调用方法继续执行的过程中完成任务。

语法分析:

(1)关键字:方法头使用 async 修饰。

(2)要求:包含 N(N>0) 个 await 表达式(不存在 await 表达式的话 IDE 会发出警告),表示需要异步执行的任务。

(3)返回类型:只能返回 3 种类型(void、Task 和 Task<T>)。Task 和 Task<T> 标识返回的对象会在将来完成工作,表示调用方法和异步方法可以继续执行。

(4)参数:数量不限,但不能使用 out 和 ref 关键字。

(5)命名约定:方法后缀名应以 Async 结尾。

(6)其它:匿名方法和 Lambda 表达式也可以作为异步对象;async 是一个上下文关键字;关键字 async 必须在返回类型前。

关于 async 关键字:

  ①在返回类型之前包含 async 关键字

  ②它只是标识该方法包含一个或多个 await 表达式,即,它本身不创建异步操作。

  ③它是上下文关键字,即可作为变量名。async/await 结构

现在先来简单分析一下这三种返回值类型:void、Task 和 Task<T>

  (1)Task<T>:调用方法要从调用中获取一个 T 类型的值,异步方法的返回类型就必须是Task<T>。调用方法从 Task 的 Result 属性获取的就是 T 类型的值。

internal class Calculato

{

private static int Add(int n, int m)

{

return n + m;

}

public static async Task<int> AddAsync(int n, int m)

{

int val = await Task.Run(() => Add(n, m));

return val;

}

}

(2)Task:调用方法不需要从异步方法中取返回值,但是希望检查异步方法的状态,那么可以选择可以返回 Task 类型的对象。不过,就算异步方法中包含 return 语句,也不会返回任何东西。

internal class Calculato

{

private static int Add(int n, int m)

{

return n + m;

}

public static async Task AddAsync(int n, int m)

{

int val = await Task.Run(() => Add(n, m));

Console.WriteLine($"Result: {val}");

}

}

控制流

异步方法的结构可拆分成三个不同的区域:

(1)表达式之前的部分:从方法头到第一个 await 表达式之间的所有代码。

(2)await 表达式:将被异步执行的代码。

(3)表达式之后的部分:await 表达式的后续部分。

该异步方法执行流程:从await表达式之前的地方开始,同步执行到第一个 await,标识着第一部分执行结束,一般来说此时 await 工作还没完成。当await 任务完成后,该方法将继续同步执行后续部分。在执行的后续部分中,如果依然存在 await,就重复上述过程。

  当到达 await 表达式时,线程将从异步方法返回到调用方法。如果异步方法的返回类型为 Task 或 Task<T>,会创建一个 Task 对象,标识需要异步完成的任务,然后将 Task 返回来调用方法。

异步方法的控制流:

  ①异步执行 await 表达式的空闲任务。

  ②await 表达式执行完成,继续执行后续部分。如再遇到 await 表达式,按相同情况进行处理。

  ③到达末尾或遇到 return 语句时,根据返回类型可以分三种情况:

    a.void:退出控制流。

    b.Task:设置 Task 的属性并退出。

    c.Task<T>:设置 Task 的属性和返回值(Result 属性)并退出。

  ④同时,调用方法将继续执行,从异步方法获取 Task 对象。需要值的时候,会暂停等到 Task 对象的 Result 属性被赋值才会继续执行。

  【难点】

  ①第一次遇到 await 所返回对象的类型。这个返回类型就是同步方法头的返回类型,跟 await 表达式的返回值没有关系。

  ②到达异步方法的末尾或遇到 return 语句,它并没有真正的返回一个值,而是退出了该方法。

await 表达式指定了一个异步执行的任务。默认情况,该任务在当前线程异步执行。

  每一个任务就是一个 awaitable 类的实例。awaitable 类型指包含 GetAwaiter() 方法的类型。

  实际上,你并不需要构建自己的 awaitable,一般只需要使用 Task 类,它就是 awaitable。

  最简单的方式是在方法中使用 Task.Run() 来创建一个 Task。【注意】它是在不同的线程上执行方法。

介绍异步方法的语法、三种不同的返回值类型(void、Task 和 Task<T>)和控制流程等。

简单常用的异步执行方式:Task.Run()。【注意】它是在不同的线程上执行方法

一、异常处理

  await 表达式也可以使用 try...catch...finally 结构。

二、在调用方法中同步等待任务

  调用方法可能在某个时间点上需要等待某个特殊的 Task 对象完成,才执行后面的代码。此时,可以采用实例方法 Wait 。

internal class Program

{

private static void Main(string[] args)

{

var t = CountCharactersAsync("http://www.cnblogs.com/liqingwen/");

t.Wait(); //等待任务结束

Console.WriteLine($"Result is {t.Result}");

Console.Read();

}

/// <summary>

/// 统计字符数量

/// </summary>

/// <param name="address"></param>

/// <returns></returns>

private static async Task<int> CountCharactersAsync(string address)

{

var result = await Task.Run(() => new WebClient().DownloadStringTaskAsync(address));

return result.Length;

}

}

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 腾玛人工智能受邀出席中国西部国际投资贸易洽谈会

    2019年5月16日,第二届中国西部国际投资贸易洽谈会(以下简称“西洽会”)在重庆国际博览中心开幕。本届“西洽会”以“开放新时代·发展新作为”为主题。据执委会初...

    腾玛人工智能
  • 人工智能腾玛与佛山市护尔智能科技有限公司达成战略合作

    2019年6月11日,腾玛人工智能与佛山市护尔智能科技有限公司正式达成战略合作,强强联手,合作共赢,携手开启“AI智能生活+数字化管理”的双核驱动模式。腾玛人工...

    腾玛人工智能
  • 人工智能腾玛湘西旗舰店盛大开业!

    精雕细琢,只为惊艳启幕。6月12日,腾玛人工智能湘西旗舰店盛大开业!全城瞩目,开启智能新王潮!腾玛人工智能总部总经理朱建铭先生、腾玛人工智能总部副总经理李冠陞先...

    腾玛人工智能
  • 电脑内存不足怎么办? 分享三个解决方法

    1、打开电脑的控制面板,点击“系统和安全”打开“系统”。然后点击页面中的“高级系统设置”。接着在“系统属性”页面中的点击性能栏里的“设置”。

    高效办公
  • Spark Core项目实战 | 页面单跳转化率统计

    大数据真好玩
  • IOS移动开发从入门到精通

    1 应用程序的5个阶段,放在 AppDelegate.swift application:didFinishLaunchingWithOptions 当应用程...

    用户5760343
  • 动态 | 微软开源可解释机器学习工具包lnterpretML

    事实上,要实现可理解性是复杂的,它高度依赖许多变量和人为因素,排除了任何“一刀切”的方法。可理解性是一个前沿的、跨学科的研究领域,它建立在机器学习、心理、人机交...

    AI科技评论
  • python3中bytes与string

    py3study
  • Android自定义带圆点的半圆形进度条

    本文实例为大家分享了Android自定义带圆点的半圆形进度条,供大家参考,具体内容如下

    砸漏
  • R语言基于Keras的小数据集深度学习图像分类

    您有时会听到深度学习仅在有大量数据可用时才有效。这部分是有效的:深度学习的一个基本特征是它可以自己在训练数据中找到有趣的特征,而不需要手动特征工程,这只有在有大...

    拓端

扫码关注云+社区

领取腾讯云代金券