C#中await/async闲说
自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要从底层开始编写,这样后边使用的时候就是异步,那么底层是如何实现??我们如何编写高效率的异步方法??
#了解基于任务的异步模式(TAP)
基于任务的异步编程模型 (TAP) 提供了异步代码的抽象化,你只需像往常一样将代码编写为一连串语句即可,在开始调用的地方运行。例如:var task = method()①; await task②; 在①的时候开始运行可能还没有运行完,在②程序挂起等待运行完,中间怎么运行的你不需要知道,编译器会做若干操作的。当开启多个任务的时候,像要他们都执行完,在执行其他的时候,可以await Task.WhenAll(task1,task2 .....);
#了解async/await
await 运算符应用于异步方法,在方法的执行中插入挂起点,直到所等待任务完成。使用async 和await定义异步方法不一定会创建新线程,当编译器看到await关键字时,线程会挂起等待运行结束。
await 仅可用于由 async 关键字修改的异步方法中,使用 async 修饰符定义的方法通常包含一个或多个 await 表达式,使用await运算符的任务通常是实现[基于任务的异步模式(TAP)]的方法调用返回,返回值包括 Task、Task<TResult>、ValueTask 和 ValueTask<TResult> 对象的方法。
# 调用 Task.Wait() 或者 Task.Result 立刻产生死锁的充分条件
1. 调用 Wait() 或 Result 的代码位于 UI 线程。
2. Task 的实际执行在其他线程,且需要返回 UI 线程。
死锁的原因:UWP、WPF、Windows Forms 程序的 UI 线程都是单线程的。为了避免产生死锁,你应该一条道走到黑, Async All the Way。或者.ConfigureAwait(false)
# ValueTask与Task的区别
7.0为async新增的ValueTask的作用(如果没有在Nuget上下载System.Threading.Tasks.Extensions,ValueTask就在这个库中),ValueTask用于值类型的异步;Task为引用类型的,每次需要分配空间。
例如:
public async Task<int> CalculateSum(int a, int b) {
if (a == && b == )
{
return ;
} return await Task.Run(() => a + b);
}
当a,b=0的时候不会运行到task里,这个时候返回task就造成了资源的浪费,修改为以下会效率更高
public async ValueTask<int> CalculateSum2(int a, int b)
{
if (a == && b == )
{
return ;
} return await Task.Run(() => a + b);
}
但是也不是说到处用ValueTask会好,当是引用类型的时候,用ValueTask,你需要关注更多的数据,这个时候用Task会更好。
# await/async原理分析
[AsyncStateMachine(typeof(Class1.<CalculateSum2>d__1))]
public ValueTask<int> CalculateSum2(int a, int b)
{
Class1.<CalculateSum2>d__1 <CalculateSum2>d__;
<CalculateSum2>d__.a = a;
<CalculateSum2>d__.b = b;
<CalculateSum2>d__.<>t__builder = AsyncValueTaskMethodBuilder<int>.Create();
<CalculateSum2>d__.<>1__state = -;
AsyncValueTaskMethodBuilder<int> <>t__builder = <CalculateSum2>d__.<>t__builder;
<>t__builder.Start<Class1.<CalculateSum2>d__1>(ref <CalculateSum2>d__);
return <CalculateSum2>d__.<>t__builder.Task;
}
对CalculateSum2代码解析,发现没有await/async,原来又是编译器提供的语法糖。
[__DynamicallyInvokable, DebuggerStepThrough, SecuritySafeCritical]
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
if (stateMachine == null)
{
throw new ArgumentNullException("stateMachine");
}
ExecutionContextSwitcher executionContextSwitcher = default(ExecutionContextSwitcher);
RuntimeHelpers.PrepareConstrainedRegions();
try
{
ExecutionContext.EstablishCopyOnWriteScope(ref executionContextSwitcher);
stateMachine.MoveNext();
}
finally
{
executionContextSwitcher.Undo();
}
}
对Start方法进行分析,可以看出MoveNext,程序的运行其实还是一步一步进行的,那么await/async会不会创建一个线程,这倒是不一定,这个由线程池决定,那么异步了不创建一个线程,怎么异步的,这里的异步可能是运行在已经有的线程上。
其他的多线程文章
2. .NET中并行开发优化
3. C# Task.Run 和 Task.Factory.StartNew 区别
4. C#中多线程的并行处理
5. C#中多线程中变量研究
C#中await/async闲说的更多相关文章
- await/async闲说
C#中await/async闲说 自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要 ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
- [C#] .NET4.0中使用4.5中的 async/await 功能实现异
好东西需要分享 原文出自:http://www.itnose.net/detail/6091186.html 在.NET Framework 4.5中添加了新的异步操作库,但是在.NET Framew ...
- 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。
[TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...
- 在MVC中使用async和await的说明
首先,在mvc中如果要用纯异步请不要使用async和await,可以直接使用Task.Run. 其次,在mvc中使用async和await可以让系统开新线程处理Task的代码,同时不必等Task执行结 ...
- 在Silverlight中使用async/await
现在 async/await 大行其道,确实,有了 async/await ,异步编程真是简单多了,个人觉得 async/await 的出现,给开发者还来的方便,绝不亚于当年 linq 的出现. 但要 ...
- 在现有代码中通过async/await实现并行
在现有代码中通过async/await实现并行 一项新技术或者一个新特性,只有你用它解决实际问题后,才能真正体会到它的魅力,真正理解它.也期待大家能够多分享解一些解决实际问题的内容. 在我们遭遇“黑色 ...
- promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解
* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...
- C# 中的Async 和 Await 的用法详解
众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...
随机推荐
- webpack之font-awesome
1.安装font-awesome和font-awesome-loader及依赖 git:https://github.com/shakacode/font-awesome-loader npm ins ...
- shell问题集合
1.syntax error near unexpected token `then' if后要有空格,[] 中括号的开头和结尾要有空格! [ $1-eq"root" ]中括号中的 ...
- hudson搭建经验总结
作者:朱金灿 来源:http://blog.csdn.net/clever101 hudson 是一种革命性的开放源码 CI (持续集成)服务器,随着工程源码越来越庞大,把源码编译工作放在本地机器已不 ...
- Android framework召回(3)binder使用和IBinder BpRefbase IInterface INTERFACE 之间的关系
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, int index, audio_devices_t de ...
- 使用WPF实现3D场景[二]
原文:使用WPF实现3D场景[二] 在上一篇的文章里我们知道如何构造一个简单的三维场景,这次的课程我将和大家一起来研究如何用代码,完成对建立好了的三维场景的观察. 首先看一下DEMO的界面: ...
- AutoEncoder一些实验结果,并考虑
看之前Autoencoder什么时候,我做了一些练习这里:http://ufldl.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder .其 ...
- 在python3下用PIL做图像处理
Python Imaging Library (PIL)是python下的图像处理模块,支持多种格式,并提供强大的图形与图像处理功能. 目前PIL的官方最新版本为1.1.7,支持的版本为python ...
- python 教程 第十九章、 图形界面编程
第十九章. 图形界面编程 import Tkinter top = Tkinter.Tk() hello = Tkinter.Label(top, text='Hello World!') hello ...
- MySQL TIMESTAMP(时间戳)详细解释
当你创建一个表假设表中有类型的字段TIMESTAMP,该字段默认情况下,语句生成: CREATE TABLE `test` ( `id` int(11) DEFAULT NULL, `ctime` t ...
- mac 端安装JAVA开发环境
一.maven安装 下载地址 https://maven.apache.org/download.cgi 下载 apache-maven-3.5.2-bin-zip 将下载的文件放在某路径下 修改 ...