一. 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. Windows下安装tomcat

    一.Tomcat下载与安装: 1.直接到官网下载Tomcat安装程序包:http://tomcat.apache.org/ 2.下载下来后是个压缩包,如:apache-tomcat-8.0.26,解压 ...

  2. 20165202 2017-2018-2 《Java程序设计》第7周学习总结

    20165202 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容总结 Ch11 连接MySQL数据库 下载JDBC-MySQL数据库驱动 加载JDBC-MySQL ...

  3. jsp中把js变量赋给java变量,或者将java变量赋给js变量怎么做?

    在jsp中经常会遇到把js变量赋给java变量,或者将java变量赋给js变量的情况,在此将通用的处理方法小结如下: java变量传给js好办,var a=”<%=javaParam%>“ ...

  4. angularjs 阻止浏览器自带的回退

    $scope.$on('$locationChangeStart', function(e) { if(!tfOrder && comm.getStorage('orederlistL ...

  5. jQuery AJAX 与 jQuery 事件

    jQuery 本身即是为事件处理而特别设计的,jQuery 事件处理方法是 jQuery 中的核心函数. $(function() { ... }); 是如下格式的缩写: $(document).re ...

  6. [IC]Lithograph(0)半导体制造的基本过程

    1. 晶圆片 Wafer 晶圆(Wafer)是指硅半导体集成电路制作所用的硅芯片,由于其形状为圆形,故称为晶圆.晶圆是生产集成电路所用的载体,一般意义晶圆多指单晶硅圆片. 半导体行业从图1到图2,是一 ...

  7. [转载][QT][SQL]sql学习记录3_sqlite之update delete like

    转载自:详见 : http://www.runoob.com/sqlite/sqlite-create-table.html 约束表实例 下面是一个实例,它创建了一个 COMPANY 表,ID 作为主 ...

  8. using中StreamWriter XmlWriter 区别

    使用StreamWriter using (var writer = new StreamWriter(File.Create(path))) { writer.WriteLine("sdf ...

  9. vps上搭建jupyter notebook远程服务

    安装anaconda 使用如下命令下载: wget https://repo.continuum.io/archive/Anaconda3-5.0.0.1-Linux-x86_64.sh 如果非roo ...

  10. 每天一个linux命令(权限):【转载】 /etc/group文件详解

    Linux /etc/group文件与/etc/passwd和/etc/shadow文件都是有关于系统管理员对用户和用户组管理时相关的文件.linux /etc/group文件是有关于系统管理员对用户 ...