async 與 Thread 的錯(cuò)誤結(jié)合

在 TAP 出現(xiàn)之前,我們可以通過 Thread 來完成一些線程操作,從而實(shí)現(xiàn)多線程和異步操作。在 TAP 出現(xiàn)之后,有時(shí)候?yàn)榱烁呔鹊目刂凭€程,我們還是會(huì)使用到 Thread 。文本講介紹一種錯(cuò)誤的使用方式,作為讀者的一個(gè)參考。
和 TaskCreateOptions.LongRunning 類似
不應(yīng)該嘗試使用 Thread 執(zhí)行類似的異步操作。因?yàn)檫@浪費(fèi)了開啟線程的花銷。
有的時(shí)候,你可能會(huì)這么寫:
Bilibili 代碼塊無法正常渲染,因此無法正常顯示。請(qǐng)關(guān)注微信公眾號(hào)“newbe技術(shù)專欄”,搜索對(duì)應(yīng)文章代碼內(nèi)容。

但其實(shí),這是個(gè)錯(cuò)誤的寫法。
IDE 提示
和 TaskCreateOptions.LongRunning 略有不同,采用這種寫法,IDE 會(huì)給出一個(gè)提示,表明希望取消 async 關(guān)鍵字。因?yàn)閷?shí)際上
Thread 的所有重載中并沒有支持 Task 相關(guān)的重載。
async void 除了在 event handler 中使用,其他地方都是不推薦的。
所以這種做法實(shí)際上并不推薦。
而 TaskFactory.StartNew() 的重載中,由于存在一個(gè) Func<T>
的重載,所以導(dǎo)致雖然這種這種使用方式錯(cuò)誤,卻被 IDE 所接受。
所以這里其實(shí)就可以總結(jié)一個(gè)簡單的規(guī)則:當(dāng)考察一組 API 是否原生支持 TAP 操作的時(shí)候,應(yīng)該查看這組 API 中是否存在 Task 相關(guān)的重載。如果沒有,那么說明原生并不能良好支持,如果使用則可能會(huì)出現(xiàn)意外的情況
同樣的,當(dāng)我們自己在設(shè)計(jì) API 的時(shí)候也應(yīng)該參考該原則,對(duì)于自己希望支持 TAP 的 API,應(yīng)該提供 Task 相關(guān)的重載。
曇花線程
在 thread async void 其實(shí)上只是一個(gè)很小的問題。這個(gè)錯(cuò)誤的關(guān)鍵還是造成了一個(gè)曇花線程。
我們通過以下代碼來驗(yàn)證:
Bilibili 代碼塊無法正常渲染,因此無法正常顯示。請(qǐng)關(guān)注微信公眾號(hào)“newbe技術(shù)專欄”,搜索對(duì)應(yīng)文章代碼內(nèi)容。

這里我們可以看到,thread.IsAlive 的值為 False。這是因?yàn)?,我們?cè)?thread 中使用了 await 關(guān)鍵字,在 await 之后的代碼,實(shí)際上是在另一個(gè) ThreadPool 中的線程中執(zhí)行的。而我們的 thread 本身在 await 之后就已經(jīng)結(jié)束了。于是我們就得到了一個(gè)曇花一現(xiàn)的線程。
而這種曇花線程無疑就是一種浪費(fèi)。
如何觀測線程的生命周期
其實(shí)大體的內(nèi)容我們已經(jīng)講完了。但為了湊一下篇幅,我們著重演示一下如何使用 Rider 來觀測線程的生命周期。
首先我們?cè)?Rider 中創(chuàng)建一個(gè)單元測試項(xiàng)目,然后在其中創(chuàng)建一個(gè)單元測試:
Bilibili 代碼塊無法正常渲染,因此無法正常顯示。請(qǐng)關(guān)注微信公眾號(hào)“newbe技術(shù)專欄”,搜索對(duì)應(yīng)文章代碼內(nèi)容。

然后我們?cè)?Rider 中按照下圖選擇 Profile 選項(xiàng):

然后選擇 Profile Unit Tests 選項(xiàng):

稍等片刻之后,我們就可以雙擊下圖中的報(bào)告,來查看線程的生命周期:

在查看界面中,我們可以通過線程下來框來查看線程運(yùn)行所花費(fèi)的時(shí)間:

如果上圖,我們可以很直接的看到,t1 線程的生命周期可以說是瞬間就結(jié)束了,因?yàn)榈谝淮?await 之后,線程就結(jié)束了。
總結(jié)
在本文中,我們演示了一種錯(cuò)誤的使用方式,以及如何使用 Rider 來觀測線程的生命周期。
參考
.NET Task 揭秘(2):Task 的回調(diào)執(zhí)行與 await1
Task2
TaskCreationOptions3
感謝您的閱讀,如果您覺得本文有用,快長按右下角大拇指??為本文點(diǎn)贊~
歡迎關(guān)注作者的微信公眾號(hào)“newbe技術(shù)專欄”,獲取更多技術(shù)內(nèi)容。

本文作者: newbe36524
本文鏈接: https://www.newbe.pro/Others/0x027-This-is-the-wrong-way-to-use-LongRunnigTask-in-csharp/
版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請(qǐng)注明出處!
https://www.cnblogs.com/eventhorizon/p/15912383.html?
https://threads.whuanle.cn/3.task/?
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcreationoptions?view=net-7.0&WT.mc_id=DX-MVP-5003606?