美文网首页C语言程序园
C#中await/async闲说

C#中await/async闲说

作者: 编程小世界 | 来源:发表于2019-06-26 19:52 被阅读0次

自从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为引用类型的,每次需要分配空间。

例如:

publicasyncTaskCalculateSum(inta,intb){if(a ==0&& b ==0)    {return0;    }returnawaitTask.Run(() => a + b);}

当a,b=0的时候不会运行到task里,这个时候返回task就造成了资源的浪费,修改为以下会效率更高

publicasyncValueTaskCalculateSum2(inta,intb){if(a ==0&& b ==0)    {return0;    }returnawaitTask.Run(() => a + b);}

但是也不是说到处用ValueTask会好,当是引用类型的时候,用ValueTask,你需要关注更多的数据,这个时候用Task会更好。

# await/async原理分析

[AsyncStateMachine(typeof(Class1.d__1))]public ValueTaskCalculateSum2(int a, int b){    Class1.d__1d__;d__.a = a;d__.b = b;d__.<>t__builder = AsyncValueTaskMethodBuilder.Create();d__.<>1__state = -1;    AsyncValueTaskMethodBuilder<>t__builder =d__.<>t__builder;<>t__builder.Startd__1>(refd__);    returnd__.<>t__builder.Task;}

对CalculateSum2代码解析,发现没有await/async,原来又是编译器提供的语法糖。

[__DynamicallyInvokable, DebuggerStepThrough, SecuritySafeCritical]public void Start(refTStateMachine stateMachine) where TStateMachine : IAsyncStateMachine{    if (stateMachine== null)    {        throw new ArgumentNullException("stateMachine");}    ExecutionContextSwitcher executionContextSwitcher = default(ExecutionContextSwitcher);RuntimeHelpers.PrepareConstrainedRegions();try    {        ExecutionContext.EstablishCopyOnWriteScope(refexecutionContextSwitcher);stateMachine.MoveNext();}    finally    {        executionContextSwitcher.Undo();}}

对Start方法进行分析,可以看出MoveNext,程序的运行其实还是一步一步进行的,那么await/async会不会创建一个线程,这倒是不一定,这个由线程池决定,那么异步了不创建一个线程,怎么异步的,这里的异步可能是运行在已经有的线程上。

看我主页简介免费C++学习资源,视频教程、职业规划、面试详解、学习路线、开发工具

每晚8点直播讲解C++编程技术。

相关文章

  • C#中await/async闲说

    自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步...

  • async / await 异步 与 Promise 的区别

    async / await 如果使用过c#的异步写法里面的async / await基本上就很快理解啦,几乎都是把...

  • 关于C# async/await的一些说明

    关于C# async/await的一些说明 下文以个人对async/await的理解为基础进行一些说明。 1、自定...

  • 2021-06-30【c#】await

    C# 中的Async 和 Await 的用法详解 - 逆骨苍狼 - 博客园 (cnblogs.com)[https...

  • async和await

    浅谈Async/Await用 async/await 来处理异步 async和await async:声明一个异步...

  • Java线程学习笔记(1)

    对于一个从C#转到Kotlin的菜鸟,C#的时候只知道async和await Task这样的操作,Kotlin也是...

  • ES8(一) —— async&await

    目录 async和普通函数的区别 await async/await处理多回调异步 async和await必须配合...

  • async

    async/await特点 async/await更加语义化,async是“异步”的简写,async functi...

  • asp.net core 中async/await 使用

    asp.net core 中async/await 使用 async/await是用来进行异步调用的形式,内部其实...

  • ES6中的好东西

    1 Await/Async 前端的回调时代我没有赶上,我赶上的是await/async时代。await和async...

网友评论

    本文标题:C#中await/async闲说

    本文链接:https://www.haomeiwen.com/subject/bephcctx.html