志在指尖
用双手敲打未来

C#中await/async闲说

自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的中央越来越多,越来越好用,只需用异步的中央都是一连串的异步,假如想要异步编程的时分,需求从底层开端编写,这样后边运用的时分就是异步,那么底层是如何完成??我们如何编写高效率的异步办法??
#理解基于任务的异步形式(TAP)
基于任务的异步编程模型(TAP)提供了异步代码的笼统化,你只需像往常一样将代码编写为一连串语句即可,在开端调用的中央运转。例如:vartask=method()①;awaittask②;在①的时分开端运转可能还没有运转完,在②程序挂起等候运转完,中间怎样运转的你不需求晓得,编译器会做若干操作的。当开启多个任务的时分,像要他们都执行完,在执行其他的时分,能够awaitTask.WhenAll(task1,task2…..);
#理解async/await
await运算符应用于异步办法,在办法的执行中插入挂起点,直到所等候任务完成。运用async和await定义异步办法不一定会创立新线程,当编译器看到await关键字时,线程会挂起等候运转完毕。
await仅可用于由async关键字修正的异步办法中,运用async修饰符定义的办法通常包含一个或多个await表达式,运用await运算符的任务通常是完成[基于任务的异步形式(TAP)]的办法调用返回,返回值包括Task、Task、ValueTask和ValueTask对象的办法。C#
#调用Task.Wait()或者Task.Result立即产生死锁的充沛条件
1.调用Wait()或Result的代码位于UI线程。
2.Task的实践执行在其他线程,且需求返回UI线程。
死锁的缘由:UWP、WPF、WindowsForms程序的UI线程都是单线程的。为了防止产生死锁,你应该一条道走到黑,AsyncAlltheWay。或者.ConfigureAwait(false)
#ValueTask与Task的区别
7.0为async新增的ValueTask的作用(假如没有在Nuget上下载System.Threading.Tasks.Extensions,ValueTask就在这个库中),ValueTask用于值类型的异步;Task为援用类型的,每次需求分配空间。
例如:
publicasyncTask<int>CalculateSum(inta,intb){
if(a==0&&b==0)
{
return0;
}
returnawaitTask.Run(()=>a+b);
}
当a,b=0的时分不会运转到task里,这个时分返回task就形成了资源的糜费,修正为以下会效率更高
publicasyncValueTask<int>CalculateSum2(inta,intb)
{
if(a==0&&b==0)
{
return0;
}
returnawaitTask.Run(()=>a+b);
}
但是也不是说四处用ValueTask会好,当是援用类型的时分,用ValueTask,你需求关注更多的数据,这个时分用Task会更好。
#await/async原理剖析
[AsyncStateMachine(typeof(Class1.d__1))]
publicValueTask<int>CalculateSum2(inta,intb)
{
Class1.d__1d__;
d__.a=a;
d__.b=b;
d__.<>t__builder=AsyncValueTaskMethodBuilder<int>.Create();
d__.<>1__state=-1;
AsyncValueTaskMethodBuilder<int><>t__builder=d__.<>t__builder;
<>t__builder.Start<Class1.d__1>(refd__);
returnd__.<>t__builder.Task;
}
对CalculateSum2代码解析,发现没有await/async,原来又是编译器提供的语法糖。
[__DynamicallyInvokable,DebuggerStepThrough,SecuritySafeCritical]
publicvoidStart(refTStateMachinestateMachine)whereTStateMachine:IAsyncStateMachine
{
if(stateMachine==null)
{
thrownewArgumentNullException(“stateMachine”);
}
ExecutionContextSwitcherexecutionContextSwitcher=default(ExecutionContextSwitcher);
RuntimeHelpers.PrepareConstrainedRegions();
try
{
ExecutionContext.EstablishCopyOnWriteScope(refexecutionContextSwitcher);
stateMachine.MoveNext();
}
finally
{
executionContextSwitcher.Undo();
}
}
对Start办法停止剖析,能够看出MoveNext,程序的运转其实还是一步一步停止的,那么await/async会不会创立一个线程,这倒是不一定,这个由线程池决议,那么异步了不创立一个线程,怎样异步的,这里的异步可能是运转在曾经有的线程上。

未经允许不得转载:IT技术网站 » C#中await/async闲说
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载