一、问题背景介绍:
今天在给一个方法加业务时,需要提前使用一个本来应该返回给调用者使用的实体。就造出了如下图所示的代码形式, 专门创建一个对象接收await task得到的实体。使用完毕之后,还要被IDE强制要求 await task一次。
然后我觉得这样await一个task两次,有点脱裤子放屁的感觉,又改造出如下的效果,用task.result的方式来阻塞获取id。
二、问题解惑
然后我网上查了一下这两个写法的区别,更迷糊了。网上对await 和task.result的区别解释有下面内容:
解释一:
一般来说,是的.await task;
将"屈服"当前线程.task.Result
将阻止当前线程.await
是异步等待; Result
是一个阻塞等待.
还有一个更小的区别:如果任务在故障状态下完成(即有异常),那么await
将(重新)按原样引发异常,但Result
会将异常包装在一个AggregateException
.
解释二:
await或者 .result/ .getwaiter().getresult() 这两个的区别在于,当遇到await会把线程挂起,开启别的线程继续后面的操作。但是遇到 .result会一直等在这里,不会开新的线程。很容易造成线程阻塞。 如果有两处使用 .result 还会导致互相等待 造成线程死锁
三、总结:
总体来看,好像用await比用.result更合适一点。
我在群内提问,有位大佬说的原话如下,我觉得非常有道理。
.result这种写法,不是不行,是不规范,微软官方倡导async到底,async await在服务端的作用不是十分明显,要看到明显的作用是在桌面端ui刷新的时候使用async 不会阻塞ui线程,服务端的话,是在一定并发量下才会发挥作用,async await还会涉及到请求线程和io线程,io线程经常是耗时的,没有async await之前,请求线程要等待io读写完成之后响应请求,然后这个请求线程才能空闲下来处理其他进来的请求,但是现在它不需要等待了,它把上下文交给了io线程来处理,甚至帮它把接下来的响应请求也处理了,它一定程度上节省了io等待的时间,快速回到请求线程池的队列中,随时准备处理接下来的请求。