C#中Task.Yield的用途深入講解
前言
最近在閱讀 .NET Threadpool starvation, and how queuing makes it worse 這篇博文時(shí)發(fā)現(xiàn)文中代碼中的一種 Task 用法之前從未見過(guò),在網(wǎng)上看了一些資料后也是云里霧里不知其解,很是困擾。今天在程序員節(jié)的大好日子里終于想通了,于是寫下這篇隨筆分享給大家,也過(guò)過(guò)專心寫博客的癮。
這種從未見過(guò)的用法就是下面代碼中的 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)單來(lái)說(shuō)就是創(chuàng)建時(shí)就已經(jīng)完成的 Task ,或者說(shuō)執(zhí)行時(shí)間為0的 Task ,或者說(shuō)是空任務(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 之后的代碼,這本來(lái)是為了解決異步操作(比如IO操作)霸占線程實(shí)際卻用不到線程的問(wèn)題,而 Task.Yield 卻產(chǎn)生了一個(gè)不僅沒(méi)有異步操作而且什么也不干的 Task ,不是吃飽了撐著嗎?
今天吃晚飯的時(shí)候終于想明白了——吃飽了沒(méi)有撐。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ì)在外婆家就餐,你來(lái)的時(shí)候比較巧,正好有位置,但你本來(lái)就不著急肚子也不太餓準(zhǔn)備慢慢吃慢慢聊,而排隊(duì)的人當(dāng)中有些人很餓很著急吃完還有事,這時(shí)你如果先點(diǎn)幾個(gè)招牌菜解解饞,然后將座位讓出來(lái),重新排隊(duì),并且排隊(duì)的人當(dāng)中像你這樣的都這么做,那些排隊(duì)中心急如焚的人真是是幸福感爆棚,外婆家的老板也笑彎了腰。你讓出座位重新排隊(duì)的愛(ài)心行為就是 await Task.Yield()
。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- C#異步方法返回void與Task的區(qū)別詳解
- C# 并行和多線程編程——Task進(jìn)階知識(shí)
- C# 并行和多線程編程——認(rèn)識(shí)和使用Task
- c# 使用Task實(shí)現(xiàn)非阻塞式的I/O操作
- 深入分析C# Task
- C#關(guān)于Task.Yeild()函數(shù)的討論
- C# task應(yīng)用實(shí)例詳解
- C#利用Task實(shí)現(xiàn)任務(wù)超時(shí)多任務(wù)一起執(zhí)行的方法
- windows下C#定時(shí)管理器框架Task.MainForm詳解
- 詳解C#中 Thread,Task,Async/Await,IAsyncResult的那些事兒
- c#異步task示例分享(異步操作)
- 基于c# Task自己動(dòng)手寫個(gè)異步IO函數(shù)
相關(guān)文章
C# PDF轉(zhuǎn)圖片(JPG,Png)的項(xiàng)目實(shí)踐
本文主要介紹了C# PDF轉(zhuǎn)圖片(JPG,Png)的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05C# 快速高效率復(fù)制對(duì)象(表達(dá)式樹)
在代碼中經(jīng)常會(huì)遇到需要把對(duì)象復(fù)制一遍,或者把屬性名相同的值復(fù)制一遍。本文將對(duì)其解決方法進(jìn)行詳細(xì)介紹。下面跟著小編一起來(lái)看下吧2017-04-04WindowsForm移動(dòng)一個(gè)沒(méi)有標(biāo)題欄的窗口的方法
這篇文章主要介紹了WindowsForm移動(dòng)一個(gè)沒(méi)有標(biāo)題欄的窗口的方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07用 C# 編寫一個(gè)停放在任務(wù)欄上的圖標(biāo)程序
用 C# 編寫一個(gè)停放在任務(wù)欄上的圖標(biāo)程序...2007-03-03