一. Awit和async的由来:

await/async本身是一个语法糖,编译器提供的一个简化编程的功能; 在C#升级和.net Framework升级的时候, 产生的, 所以说并不是CLR的产物

二. 用法:

a)   Async出现在方法的声明上, 任何一个方法添加一个async关键字都不会报错

b)   如果只有awit, 是会报错的

c)   Awit必须放在task前面, 必须和async成对出现

d)   Awit和async成对出现, 会被编译成状态机

三. 一个简单的示例:

private static async void NoReturn()
{
//主线程执行
Console.WriteLine($"NoReturn Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
TaskFactory taskFactory = new TaskFactory();
//主线程启动一个子线程执行
Task task = taskFactory.StartNew(() =>
{
Console.WriteLine($"NoReturn Sleep before,ThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(3000);
Console.WriteLine($"NoReturn Sleep after,ThreadId={Thread.CurrentThread.ManagedThreadId}");
});
await task;//主线程碰到await就返回去执行主线程的其它任务(循环), 而这个方法的下面的代码则不再执行, 等待主线程把其它任务执行完毕, 程序会再次跳回来执行这个方法的下面的其它代码; 但是注意, 再次跳回来的时候, 并不一定是主线程执行, 也有可能是新开一个线程来执行
//这个回调的线程是不确定的:可能是主线程 可能是子线程 也可能是其他线程
Console.WriteLine($"NoReturn Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
} //调用代码: NoReturn();
for (int i = 0; i < 10; i++)
{
Thread.Sleep(300);
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId} i={i}"); }

四. Await和async的返回值

a) 当使用await和async时, 如果没有返回值, 则应该标明使用Task作为返回值, 下面的代码演示没有返回值的await和async:

private static async Task  NoReturnTask()
{
//这里还是主线程的id
Console.WriteLine($"NoReturnTask Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); Task task = Task.Run(() =>
{
Console.WriteLine($"NoReturnTask Sleep before,ThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(3000);
Console.WriteLine($"NoReturnTask Sleep after,ThreadId={Thread.CurrentThread.ManagedThreadId}");
});
await task;
Console.WriteLine($"NoReturnTask Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); }

 b)  当使用await和async时, 如果有返回值, 则应该和Task组成泛型来返回: Task<typeName>, 下面的代码演示有返回值的await和async

private static async Task<long> SumAsync()
{
Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long result = 0;
//1. 先启动一个线程, 主线程遇到这里之后, 就会返回去了, 这个子线程开始执行
await Task.Run(() =>
{
for (long i = 0; i < 999999999; i++)
{
result += i;
}
});
return result;
}

c)  Awati和async返回值的使用:

Task<long> t = SumAsync();
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long lResult = t.Result;//当需要访问result时, 则当前线程必须等待t线程的完成
t.Wait();//等价于上一行

五.  利用await和async像写同步代码一样编写异步执行的代码, 调用方法和第四步的c相同:

/// <summary>
/// 带返回值的Task
/// 要使用返回值就一定要等子线程计算完毕
/// </summary>
/// <returns>async 就只返回long</returns>
private static async Task<long> SumAsync()
{
//在await 和 async 中, 先启动一个线程, 执行完成之后, 接着可以继续awit
//有点类似同步的方式编程, 但是却是异步执行 Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long result = 0;
//1. 先启动一个线程, 主线程遇到这里之后, 就会返回去了, 这个子线程开始执行
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
} for (long i = 0; i < 999999999; i++)
{
result += i;
}
});
//2. 上面的线程执行完成之后, 输出下面这句话; 可以看做这里是其它的动作
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); //3. 然后继续执行下面这里的线程, 这里又有一个await, 然后主线程又返回去执行其他的
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
} for (long i = 0; i < 999999999; i++)
{
result += i;
}
});
//4. 这个线程执行完成之后, 开始执行这里输出
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); //5. 碰到await之后, 开了一个子线程, 然后又返回去了
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
} for (long i = 0; i < 999999999; i++)
{
result += i;
}
}); Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); return result;
}

六. 总结:

    // 1 使用async和await , 能够像写同步代码的方式一样, 达到异步执行的功能

      // 2 如果 awit / async 没有返回值, 则使用Task来替代(虽然允许写成void, 但是不要那样做);无返回值时  async Task == async void

      // 3 如果有返回值则使用Task<类型> 来处理

     // 4 await只能出现在Task前面

     // 5 不能单独await

     // 6 await 只能放在task前面

    // 7 不管你的await和async标识的方法需不需要返回值, 都不推荐void返回, 应该使用Task来代替, 像第二条所说那样, 因为返回Task和Task<T>则能够使用await, 并且可以和Task.WhenAny, Task.WhenAll等方式组合使用, 但是如果返回Void 不行, 则这条线程链就断了

    // 8 如果 awit / async 没有返回值, 则使用Task来替代, 如果有返回值则使用Task<类型>来处理

  

20181110_wait和async的更多相关文章

  1. [C#] async 的三大返回类型

    async 的三大返回类型 序 博主简单数了下自己发布过的异步文章,已经断断续续 8 篇了,这次我想以 async 的返回类型为例,单独谈谈. 异步方法具有三个可让开发人员选择的返回类型:Task&l ...

  2. async & await 的前世今生(Updated)

    async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...

  3. [.NET] 利用 async & await 的异步编程

    利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html  目录 异步编程的简介 异 ...

  4. [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程

    怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html  ...

  5. [.NET] 利用 async & await 进行异步 IO 操作

    利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html  序 上次,博主 ...

  6. [C#] 走进异步编程的世界 - 开始接触 async/await

    走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async/await,但在控制台输出示例时经常会采用 C# 6.0 的 $&qu ...

  7. [译] C# 5.0 中的 Async 和 Await (整理中...)

    C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...

  8. await and async

    Most people have already heard about the new “async” and “await” functionality coming in Visual Stud ...

  9. C# await和async

    基础阅读:http://www.cnblogs.com/jesse2013/p/async-and-await.html 答疑阅读:http://www.cnblogs.com/heyuquan/ar ...

随机推荐

  1. Linux下的软件的安装

     一.yum相关介绍及命令 [1] 用来管理软件的一个命令.通过该命令完成对软件的下载.卸载等操作. [2] 命令:(必须在yum搭建成功后才能正常运行) yum  clean all      清楚 ...

  2. 三张图看懂 clientheight、offsetheight、scrollheight

    clientheight clientheigh: 内容的可视区域,不包含border. clientheight=padding + height - 横向滚动轴高度. The Element.cl ...

  3. 《gradle 用户指南中文版》目录

    gradle 用户指南 版权所有©2007-2017 Hans Dockter,Adam Murdoch只要您不对这些副本收取任何费用,并且进一步规定,每个副本都包含本版权声明,无论是以印刷版还是电子 ...

  4. OpenGL实现相机视频NV21格式转RGB格式

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  5. 服务上部署jmeter远程机

    1.首先连接服务器 2.在/home下新创建一个自己的文件夹 ]#useradd zhuxiao ]#ls 显示新的用户并在home下创建zhuxiao文件夹 ①切换到用户zhuxiao目录下 ]#s ...

  6. apt-get -f install

    http://zhidao.baidu.com/link?url=tZLEfm1Ycc1pWS67-95fXU596CtwA_1l2pPfzINUTxvOCvWdf3JZsWuZNxsxn0Jv6Om ...

  7. HDU1496 Equations 卡时间第二题

    Consider equations having the following form: a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 a, b, c, d are integers ...

  8. xml的读取(曾删改)

    获取XML 得到 需要查询的字段名 private string GetXml(string TableName) { try { string TbName = TableName.Split('_ ...

  9. Quartz 2D编程指南(2) - 图形上下文

    一个Graphics Context表示一个绘制目标.它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息.Graphics Context定义了基本的绘制属性,如颜色.裁减区域.线条宽度和样式信息 ...

  10. LeetCode 773. Sliding Puzzle

    原题链接在这里:https://leetcode.com/problems/sliding-puzzle/description/ 题目: On a 2x3 board, there are 5 ti ...