20181110_wait和async
一. 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的更多相关文章
- [C#] async 的三大返回类型
async 的三大返回类型 序 博主简单数了下自己发布过的异步文章,已经断断续续 8 篇了,这次我想以 async 的返回类型为例,单独谈谈. 异步方法具有三个可让开发人员选择的返回类型:Task&l ...
- async & await 的前世今生(Updated)
async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...
- [.NET] 利用 async & await 的异步编程
利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html 目录 异步编程的简介 异 ...
- [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程
怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html ...
- [.NET] 利用 async & await 进行异步 IO 操作
利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html 序 上次,博主 ...
- [C#] 走进异步编程的世界 - 开始接触 async/await
走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async/await,但在控制台输出示例时经常会采用 C# 6.0 的 $&qu ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
- await and async
Most people have already heard about the new “async” and “await” functionality coming in Visual Stud ...
- C# await和async
基础阅读:http://www.cnblogs.com/jesse2013/p/async-and-await.html 答疑阅读:http://www.cnblogs.com/heyuquan/ar ...
随机推荐
- php远程文件包含截断问题
今天在学习<白帽子讲web安全>一书是,提到一个php远程文件包含漏洞 可以从攻击者服务器中的一个写好的攻击脚本中远程执行命令 服务器中有漏洞的页面代码为: #test.php#error ...
- L152
For the first time, one of the new immunotherapy drugs has shown promise against breast cancer in a ...
- LINUX系统下的shell命令---grep、sed、awk
1)grep文本过滤命令 1.grep基本认识 (Global search regular expression and print out the line全局搜索研究正则表达时并显示出 ...
- inet_pton函数和inet_ntop函数的用法及简单实现
http://blog.csdn.net/eagle51/article/details/53157643?utm_source=itdadao&utm_medium=referral 这两个 ...
- Vim技能修炼教程(2) - 语法高亮速成
语法高亮速成 我们继续在人间修行Vim技能之旅.上一次我们学习了如何通过vundle安装插件,这次我们迅速向写插件的方向挺进. 我们先学习一个最简单的语法高亮插件的写法. 语法高亮基本上是由三部分组成 ...
- Microsoft Office Powerpoint、Visio 已停止工作解决办法
现象:在使用visio的过程中经常会出现“Microsoft office visio已停止工作”只能将visio关闭:windows可以尝试恢复您的信息并重新启动该程序.office的其他组件不会出 ...
- Android学习笔记之Android Studio下创建menu布局文件
1.创建menu文件夹 Android Studio项目中如果没有menu文件夹,在res文件夹右键,new-Android resource directory: 则会弹出下图对话框,在Resour ...
- linux 下 Linux 下char转换为wchar_t 设置本地为utf-8编码 以及wchar 的输入输出
LInux下使用mbstowcs函数可以将char转化为wchar_t函数含义:convert a multibyte string to a wide char string说明: Th ...
- 使用POI对excel进行操作生成二维数组
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...
- MySQL的一些常用sql函数(持续更新。。)
1. 字符串拼接函数 :CONCAT(str1,str2,...) SELECT CONCAT('AAA','BBB') STR; //AAABBB 2. 判断是否为null,为null就指定另外一个 ...