终于明白了 C# 中 Task.Yield 的用途
最近在閱讀?.NET Threadpool starvation, and how queuing makes it worse?這篇博文時(shí)發(fā)現(xiàn)文中代碼中的一種 Task 用法之前從未見過,在網(wǎng)上看了一些資料后也是云里霧里不知其解,很是困擾。今天在程序員節(jié)的大好日子里終于想通了,于是寫下這篇隨筆分享給大家,也過過專心寫博客的癮。
這種從未見過的用法就是下面代碼中的?await Task.Yield()?:
static async Task Process(){ ??await Task.Yield(); ?
??var tcs = new TaskCompletionSource<bool>();Task.Run(() =>{Thread.Sleep(1000);tcs.SetResult(true);});tcs.Task.Wait(); }
(注:上面的代碼不是示例,只是因?yàn)檫@段代碼而初遇 await Task.Yield)
Task.Yield 簡(jiǎn)單來說就是創(chuàng)建時(shí)就已經(jīng)完成的 Task ,或者說執(zhí)行時(shí)間為0的 Task ,或者說是空任務(wù),也就是在創(chuàng)建時(shí)就將 Task 的 IsCompeted 值設(shè)置為0。
那 await 一個(gè)空任務(wù)會(huì)怎樣?我們知道在 await 時(shí)會(huì)釋放當(dāng)前線程,等所 await 的 Task 完成時(shí)會(huì)從線程池中申請(qǐng)新的線程繼續(xù)執(zhí)行 await 之后的代碼,這本來是為了解決異步操作(比如IO操作)霸占線程實(shí)際卻用不到線程的問題,而 Task.Yield 卻產(chǎn)生了一個(gè)不僅沒有異步操作而且什么也不干的 Task ,不是吃飽了撐著嗎?
今天吃晚飯的時(shí)候終于想明白了——吃飽了沒有撐。Task.Yield 產(chǎn)生的空任務(wù)僅僅是為 await 做嫁衣,而真正的圖謀是借助 await 實(shí)現(xiàn)線程的切換,讓 await 之后的操作重新排隊(duì)從線程池中申請(qǐng)線程繼續(xù)執(zhí)行。這樣做有什么好處呢?線程是非常非常寶貴的資源,千金難買一線程,而且有優(yōu)先級(jí),提高線程利用率的重要手段之一就是及時(shí)將線程分配給最需要的地方,而最奢侈的之一是讓一個(gè)優(yōu)先級(jí)低執(zhí)行時(shí)間長(zhǎng)的操作一直占用著一個(gè)線程,await Task.Yield 可以讓你巧妙地借助 await 的線程切換能力,將不太重要的比較耗時(shí)的操作放在新的線程(重新排隊(duì)從線程池中申請(qǐng)到的線程)中執(zhí)行。打個(gè)比方,很多人排隊(duì)在外婆家就餐,你來的時(shí)候比較巧,正好有位置,但你本來就不著急肚子也不太餓準(zhǔn)備慢慢吃慢慢聊,而排隊(duì)的人當(dāng)中有些人很餓很著急吃完還有事,這時(shí)你如果先點(diǎn)幾個(gè)招牌菜解解饞,然后將座位讓出來,重新排隊(duì),并且排隊(duì)的人當(dāng)中像你這樣的都這么做,那些排隊(duì)中心急如焚的人真是是幸福感爆棚,外婆家的老板也笑彎了腰。你讓出座位重新排隊(duì)的愛心行為就是?await Task.Yield()。
祝大家程序員節(jié)快樂!
補(bǔ)充 - 后來發(fā)現(xiàn)的相關(guān)鏈接:
出讓執(zhí)行權(quán):Task.Yield, Dispatcher.Yield:?https://walterlv.com/post/yield-in-task-dispatcher.html?
原文地址:?https://www.cnblogs.com/dudu/p/task-yield.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com 
總結(jié)
以上是生活随笔為你收集整理的终于明白了 C# 中 Task.Yield 的用途的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: MonkeyFest2018 微软最有价
 - 下一篇: aspnet core 2.1中使用jw