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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

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

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

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

?

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

?

我多次獲得這樣一個問題:

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

?

概述

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

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

?

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

“不是,不用釋放你持有的Task,除非性能報告或可伸縮性測試報告顯示你需要釋放Task以滿足你的性能目標。如果你發現一個需要被釋放的Task,必須100%確保在你的釋放點處該Task已經完成并且沒有被其他地方在使用。”

?

3.?????????下面,你可以找一個休閑的閱讀時間,這是我對該問題的長回答:

?

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

.NET Framework設計指南中指出:一個類型如果持有其它實現過IDisposable接口的資源時,其自身也應該實現IDisposable接口。在Task內部,可能會分配一個WaitHandle對象用于等待任務完成。WaitHandle實現IDisposable接口因為它持有SafeWaitHandle內核等待句柄,所以Task實現了IDisposable接口。如果不主動釋放SafeWaitHandle句柄,最終終結器也會將其清理,但是不能對此資源立即清理并且還將此清理工作負荷遺留給系統。通過給Task實現IDisposable接口,我們可以讓開發人員能主動及時的對資源進行釋放。

?

問題

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

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中,一個Task一旦被釋放,它的大多數成員訪問都會拋出ObjectDisposedExceptions異常。這使得完成的任務很難被安全的緩存,因為一個消費者釋放Task后,另一個消費者無法再訪問Task的一些重要成員,如ContinueWith()方法或Result屬性。

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

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();

?????????然而,當使用Task的延續任務時,就很難判斷它什么時候完成它們和什么時候沒有人再使用它們,比如:

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

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

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

但是我們不能釋放第二個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,我需要進行像下面這樣的重寫:

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;

?

解決方案

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

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

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

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

?

指南

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

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

?

更多資源來源博文:關于Async與Await的FAQ

?

?

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

作者:Stephen Toub - MSFT

?

?


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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。