日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

【转】1.B(译).NET4.X并行任务Task需要释放吗?

發(fā)布時(shí)間:2023/12/10 asp.net 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】1.B(译).NET4.X并行任务Task需要释放吗? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送門:異步編程系列目錄……

?

摘要:本博文解釋在.NET 4.X中的Task使用完后為什么不應(yīng)該調(diào)用Dispose()。并且說明.NET4.5對(duì).NET4.0的Task對(duì)象進(jìn)行的部分改進(jìn):減輕Task對(duì)WaitHandle對(duì)象的依賴,并且增強(qiáng)在釋放了Task后對(duì)其成員的可訪問性。

?

我多次獲得這樣一個(gè)問題:

?????????“Task實(shí)現(xiàn)了IDisposable接口并且公開Dispose()方法,這是否意味著我們要對(duì)所有的任務(wù)進(jìn)行釋放嗎?”

?

概述

1.?????????這是我對(duì)該問題的簡要回答:

“不是,不用釋放你持有的Task。”

?

2.?????????這是我對(duì)該問題的中篇回答:

“不是,不用釋放你持有的Task,除非性能報(bào)告或可伸縮性測試報(bào)告顯示你需要釋放Task以滿足你的性能目標(biāo)。如果你發(fā)現(xiàn)一個(gè)需要被釋放的Task,必須100%確保在你的釋放點(diǎn)處該Task已經(jīng)完成并且沒有被其他地方在使用。”

?

3.?????????下面,你可以找一個(gè)休閑的閱讀時(shí)間,這是我對(duì)該問題的長回答:

?

為什么要調(diào)用Task的Dispose()?

.NET Framework設(shè)計(jì)指南中指出:一個(gè)類型如果持有其它實(shí)現(xiàn)過IDisposable接口的資源時(shí),其自身也應(yīng)該實(shí)現(xiàn)IDisposable接口。在Task內(nèi)部,可能會(huì)分配一個(gè)WaitHandle對(duì)象用于等待任務(wù)完成。WaitHandle實(shí)現(xiàn)IDisposable接口因?yàn)樗钟蠸afeWaitHandle內(nèi)核等待句柄,所以Task實(shí)現(xiàn)了IDisposable接口。如果不主動(dòng)釋放SafeWaitHandle句柄,最終終結(jié)器也會(huì)將其清理,但是不能對(duì)此資源立即清理并且還將此清理工作負(fù)荷遺留給系統(tǒng)。通過給Task實(shí)現(xiàn)IDisposable接口,我們可以讓開發(fā)人員能主動(dòng)及時(shí)的對(duì)資源進(jìn)行釋放。

?

問題

?????????如果為每一個(gè)Task都分配一個(gè)WaitHandle,那么釋放Task將是一個(gè)好措施因?yàn)檫@樣能提高性能。但是事實(shí)并非如此,現(xiàn)實(shí)中,為Task分配WaitHandle的情況是非常少出現(xiàn)的。.NET 4.0中,WaitHandle在以下幾種情況會(huì)延遲初始化:訪問?((IAsyncResult)task).AsyncWaitHandle成員,或者調(diào)用Task的WaitAll()/WaitAny()方法(這兩個(gè)方法在.NET4.0版本中,內(nèi)部是基于Task的WaitHandle對(duì)象實(shí)現(xiàn)的)。這使得回答“是否應(yīng)該釋放Task”問題更加困難了,因?yàn)槿绻鸗ask都使用了WaitAll()/WaitAny(),那么釋放Task就是一個(gè)好選擇。

1 2 3 4 5 6 7 public?interface?IAsyncResult { ????object?AsyncState { get; } ????WaitHandle AsyncWaitHandle { get; } ????bool?CompletedSynchronously { get; } ????bool?IsCompleted { get; } }

?????????在.NET 4.0中,一個(gè)Task一旦被釋放,它的大多數(shù)成員訪問都會(huì)拋出ObjectDisposedExceptions異常。這使得完成的任務(wù)很難被安全的緩存,因?yàn)橐粋€(gè)消費(fèi)者釋放Task后,另一個(gè)消費(fèi)者無法再訪問Task的一些重要成員,如ContinueWith()方法或Result屬性。

?????????這里還有另外一個(gè)問題:Task是基礎(chǔ)同步基元。如果Task被用于并行化,如在一個(gè)fork/join模式(”分支/合并”模式)中那么它就很容易知道什么時(shí)候完成它們和什么時(shí)候沒有人再使用它們,比如:

1 2 3 4 5 6 var?tasks = new?Task[3]; tasks[0] = Compute1Async(); tasks[1] = Compute2Async(); tasks[2] = Compute3Async(); Task.WaitAll(tasks); foreach(var?task in?tasks) task.Dispose();

?????????然而,當(dāng)使用Task的延續(xù)任務(wù)時(shí),就很難判斷它什么時(shí)候完成它們和什么時(shí)候沒有人再使用它們,比如:

1 2 3 4 5 Compute1Async().ContinueWith(t1 => { ????t1.Dispose(); ????… });

示例成功的釋放掉Compute1Async()返回的Task,但是它忽略了如何釋放ContinueWith()返回的Task。當(dāng)然,我們能使用同樣的方法釋放這個(gè)Task。

1 2 3 4 5 Compute1Async().ContinueWith(t1 => { ????t1.Dispose(); ????… }).ContinueWith(t2 => t2.Dispose());

但是我們不能釋放第二個(gè)ContinueWith()返回的Task。即使使用C#5.0中新的async/await異步方法也不能解決。例如:

1 2 3 string?s1 = await Compute1Async(); string?s2 = await Compute2Async(s1); string?s3 = await Compute3Async(s2);

如果想釋放這些Task,我需要進(jìn)行像下面這樣的重寫:

1 2 3 4 5 6 7 string?s1 = null, s2 = null, s3 = null; using(var?t1 = Compute1Async()) ????s1 = await t1; using(var?t2 = Compute2Async(s1)) ????s2 = await t2; using(var?t3 = Compute3Async(s2)) ????s3 = await t3;

?

解決方案

?????????由于像上面這樣進(jìn)行釋放大多數(shù)Task顯得很繁瑣,所以在.NET4.5中已經(jīng)對(duì)Task的Dispose()做過一些改進(jìn):

1.?我們使得你更少機(jī)會(huì)為Task創(chuàng)建WaitHandle對(duì)象。在.NET4.5中我們已經(jīng)重寫了Task的WaitAll()和WaitAny()以致這兩個(gè)方法不再依賴與WaitHandle對(duì)象(這樣WaitAll()、WaitAny()、Wait()就都基于自旋等待),避免在Task的內(nèi)部實(shí)現(xiàn)中使用WaitHandle對(duì)象,并且提供async/await相關(guān)異步功能。因此,只有當(dāng)你顯示訪問Task的IAsyncResult.AsyncWaitHandle成員才會(huì)為Task分配WaitHandle對(duì)象,但這種需求非常少見。這意味著除了這種非常少見的情況外,釋放一個(gè)任務(wù)是不需要的。

2.??????我們使得Task在釋放后依然可用。你能使用Task的所有公開成員即使Task已經(jīng)被釋放,訪問這些成員的表現(xiàn)就和釋放Task之前一樣。只有IAsyncResult.AsyncWaitHandle成員你不能使用,因?yàn)檫@是你釋放Task時(shí)真真所釋放的對(duì)象,當(dāng)你嘗試在釋放Task后訪問這個(gè)屬性時(shí)依然會(huì)拋出ObjectDisposedException。此外,更進(jìn)一步的說,現(xiàn)在我們推薦使用async/await異步方法以及基于任務(wù)的異步編程模式,降低對(duì)IAsyncResult的使用,即使你繼續(xù)使用((IAsyncResult)task),調(diào)用其AsyncWaitHandle成員也是十分罕見的。

3.?????????Task.Dispose()方法在“.NET Metro風(fēng)格應(yīng)用程序”框架所引用的程序集中甚至并不存在(即此框架中Task沒有實(shí)現(xiàn)IDisposable接口)。

?

指南

所以,這又讓我們回到了簡要的回答:“不是,不用釋放你的Task。”通常很難找到一個(gè)合適的釋放點(diǎn),目前幾乎沒有一個(gè)理由需要去主動(dòng)釋放Task(因?yàn)檎{(diào)用((IAsyncResult)task).AsyncWaitHandle成員的需求是十分罕見的),并且在“.NET Metro風(fēng)格應(yīng)用程序”框架所引用的程序集中你甚至不能調(diào)用Task的Dispose()方法。?

???????????????????

?

更多資源來源博文:關(guān)于Async與Await的FAQ

?

?

原文:http://blogs.msdn.com/b/pfxteam/archive/2012/03/25/10287435.aspx

作者:Stephen Toub - MSFT

?

?


作者:滴答的雨
出處:http://www.cnblogs.com/heyuquan/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。

總結(jié)

以上是生活随笔為你收集整理的【转】1.B(译).NET4.X并行任务Task需要释放吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。