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会不会创立一个线程,这倒是不一定,这个由线程池决议,那么异步了不创立一个线程,怎样异步的,这里的异步可能是运转在曾经有的线程上。

© 版权声明
好牛新坐标
版权声明:
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com

相关文章