C#異步編程應(yīng)該注意什么-創(chuàng)新互聯(lián)

小編這次要給大家分享的是C#異步編程應(yīng)該注意什么,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

專注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)制作、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)撫順免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上1000+企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

盡量不要編寫返回值類型為void的異步方法

在通常情況下,建議大家不要編寫那種返回值類型為void的異步方法,因?yàn)檫@樣做會破壞該方法的啟動(dòng)者與方法本身之間的約定,這套約定本來可以確保主調(diào)方能夠捕獲到異步方法所發(fā)生的異常。

正常的異步方法是通過它返回的Task對象來匯報(bào)異常的。如果執(zhí)行過程中發(fā)生了異常,那么Task對象就進(jìn)入了faulted(故障)狀態(tài)。主調(diào)方在對異步方法所返回的Task對象做await操作時(shí),該對象若已處在faulted狀態(tài),系統(tǒng)則會將執(zhí)行異步方法的過程中所發(fā)生的異常拋出,反之,若Task尚未執(zhí)行到拋出異常的那個(gè)地方,則主調(diào)方的執(zhí)行進(jìn)度會暫停在await語句這里,等系統(tǒng)稍后安排某個(gè)線程繼續(xù)執(zhí)行該語句下方的那些代碼時(shí),異常才會拋出。

總結(jié)一句話就是:void的異步方法發(fā)生異常時(shí),開發(fā)者得不到任何通知,程序既不會觸發(fā)普通的異常處理程序,也不會把這些異常記錄下來。總之,這會讓相關(guān)的線程默默的終止掉。

不要把同步方法與異步方法組合起來使用

用async關(guān)鍵字來修飾的方法意味著該方法有可能會在執(zhí)行完所有工作之前就把控制權(quán)返回給主調(diào)方,而且,它返回給主調(diào)方的是個(gè)代表工作進(jìn)度的Task對象。主調(diào)方可以查詢此對象的狀態(tài),以了解該工作是否已經(jīng)完成、尚未完成還是在執(zhí)行過程中發(fā)生了故障。此外,這種方法還在暗示主調(diào)方:本方法所執(zhí)行的工作可能要花費(fèi)很長時(shí)間,因此建議你先去做其他一些事情,稍后再來向我索要結(jié)果。

與此相反,如果把某個(gè)方法設(shè)計(jì)成同步方法,那么意味著當(dāng)該方法執(zhí)行完畢時(shí),它的后置條件必定能夠得到滿足。無論這個(gè)方法要花多長時(shí)間去完成工作,它都會采用與主調(diào)方相同的資源來完成,主調(diào)方必須等這個(gè)方法徹底執(zhí)行完畢才能向下執(zhí)行。

這兩種方法單獨(dú)寫起來都很清晰,但是如果把他們組合在一起就會讓方法變得十分難用,而且有可能導(dǎo)致各種bug,如死鎖。因此,這里提出兩條重要的原則。第一,不要讓同步方法必須等待異步方法執(zhí)行完畢才能往下執(zhí)行(盡量不用Wait()以及.result這些阻塞式的方法)。第二,不要讓異步方法把雖然耗時(shí)很長、計(jì)算量很大但是完全可以由自己執(zhí)行的工作轉(zhuǎn)交給另一個(gè)異步任務(wù)去做。'

當(dāng)然對于第二點(diǎn),這并不是說計(jì)算量較大的任務(wù)絕對不能放在單獨(dú)的線程中執(zhí)行,而是說不應(yīng)該把只用一個(gè)線程就能迅速做好的任務(wù)刻意的拆解成許多個(gè)較小的部分,并把他們分別放在多個(gè)新的線程上執(zhí)行,而是應(yīng)該把整個(gè)任務(wù)都交給某個(gè)線程來執(zhí)行才對。

使用異步方法時(shí)應(yīng)盡量避免線程分配

異步任務(wù)看上去好像很神奇,因?yàn)檫@種任務(wù)刻意轉(zhuǎn)移到另一個(gè)地方去做,使得開啟這項(xiàng)任務(wù)的異步方法可以在該任務(wù)完成之后,從早前暫停的地方繼續(xù)往下推進(jìn)。不過,要想發(fā)揮異步任務(wù)的功效,就必須保證把這項(xiàng)任務(wù)交出去確實(shí)能夠少占用一些資源,而不是僅僅會在相似的資源之間進(jìn)行上下文切換。

如:對于一個(gè)控制臺程序,如果只是執(zhí)行一項(xiàng)計(jì)算量較大且耗時(shí)較長的任務(wù)(或者說,運(yùn)行時(shí)間較長的CPU密集型的任務(wù)),那么把該任務(wù)單獨(dú)放在另一個(gè)線程中并沒有多大好處。因?yàn)檫@樣做只能讓工作線程始終處于繁忙狀態(tài),而主線程則必須一直卡在那里等待工作線程把任務(wù)做完。在這種情況下,實(shí)際上是用兩個(gè)線程來完成原本只需要一個(gè)線程就能做好的工作,造成了資源的浪費(fèi)。

避免不必要的上下文切換

目前C#代碼中使用async以及await實(shí)現(xiàn)的異步方法默認(rèn)是把a(bǔ)wait之后的代碼放在早前捕獲的那個(gè)上下文中執(zhí)行的,這是因?yàn)檫@樣做比較穩(wěn)妥,它最多只會引發(fā)幾次無謂的上下文切換,而不會使程序出現(xiàn)重大的錯(cuò)誤,與之相反,如果系統(tǒng)不把山下文切換回去,那么萬一遇到的是只能在特定的上下文中才能執(zhí)行的代碼,那么程序就有可能崩潰。因此,無論有沒有必要切換上下文,系統(tǒng)都會切換至早前捕獲到的那個(gè)上下文,并把a(bǔ)wait之后的語句放在那個(gè)上下文執(zhí)行。

如果不想讓系統(tǒng)做出這樣的安排,那么可以調(diào)用ConfigureAwait()方法。這表示接下來的那些代碼無須放在早前捕獲的上下文中執(zhí)行。例如在很多程序集中,await語句之后的那些代碼一般都與上下文無關(guān),因此與,可以調(diào)用Task對象的ConfigureAwait()方法告訴系統(tǒng),在執(zhí)行完這項(xiàng)任務(wù)之后,不必專門把a(bǔ)wait下面的代碼放在早前捕獲的上下文中運(yùn)行。如下所示:

public static async Task<XElement> ReadPacket(string url)
{
	var result=await DownloadAsync(url)
				.ConfigureAwait(false);
	return XElement.Parse(result);			
}

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享文章:C#異步編程應(yīng)該注意什么-創(chuàng)新互聯(lián)
網(wǎng)頁URL:http://bm7419.com/article14/dgoige.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、全網(wǎng)營銷推廣自適應(yīng)網(wǎng)站、微信公眾號企業(yè)網(wǎng)站制作、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司