簡體   English   中英

.NET中的托管與非托管資源。有什么不同?

[英]Managed vs Unmanaged Resources in .NET. What's the difference?

我正在閱讀Wrox的專業C#4和.NET 4章節“內存管理和指針”,特別是關於Garbage Collection如何在.NET中運行。 它說“垃圾收集器不知道如何釋放非托管資源(例如文件句柄,網絡連接和數據庫連接)”的原因,這就是為什么這些類應該聲明析構函數 (也稱為“終結器”)或實現IDisposable

似乎所有這些“非托管資源”的示例都與從應用程序外部並獨立於.NET Framework的系統交互相關。 但是,我不確定這是否是正在進行的完全區分,因此,

非托管資源和托管資源沒有的獨特特征究竟是什么?

你做對了:
托管資源由CLR管理,非托管資源不管理。 換句話說:托管資源僅存在於.NET世界中,而非托管資源來自正常的Win32世界。

使用托管資源(即內存),您不必擔心使用它們后會發生什么; CLR負責這一點。

非使用資源(有幾種類型:Windows內核對象,GDI對象,USER對象) 必須在使用完后釋放回系統 當您的進程終止時會自動發生這種情況,但如果它在此期間泄漏,則會出現一個大問題,因為您正在泄漏系統中所有進程之間共享的資源。

當然,.NET中有幾個類包裝這些非托管資源(使用dispose / finalize模式 )並為您完成艱苦的工作。 如果可以,請使用它們。

我會說,通常使用.Net框架創建的任何東西都是托管資源。 在內部,他們可能會使用非托管資源,但從您的角度來看,他們是受管理的。 其中一個例外是你P / Invoke。 雖然您創建了一個與.Net一起使用的函數,但是調用會在.Net“沙箱”之外傳遞,因此被認為是不受管理的。

對@supercat的回應

來自長期存在的對象的事件可能完全在.net框架內處理,但它們肯定需要被視為非托管資源以防止內存泄漏

我認為這里有兩個不同的東西。 有關托管與非托管的討論,並討論了應用程序的內存管理。 您可能應該將某些對象視為不受管理,但這並不意味着它們不受管理。 例如,我會考慮使用Brush類進行托管,但是你應該通過調用Dispose()將其視為非托管類。 在類中隱藏/抽象是您希望Dispose()負責的非托管對象。 Dispose()實際上並沒有釋放任何資源,它只是一個你希望開發人員正確實現的模式。

為了更進一步,我想說大多數非托管對象是通過調用CreateXYZ() Win32方法創建的,該方法返回一個指針但需要使用帶有相同指針的`DestroyXYZ()/ DeleteXYZ()'方法釋放。 另一方面,托管對象實現Dispose / Finalize為您執行此操作。 再一次,您希望托管資源的編寫者已經做到了這一點,但並不能保證。

“非托管資源”一詞令人困惑。 一個更有用的概念是“清理責任”。 如果一個對象擁有非托管資源,那意味着三件事:

  1. 它操縱一些外部長壽的實體,
  2. 該實體可能處於需要清理的狀態,並且
  3. 該對象負責提供所需的清理

通常,術語“受管資源”用於表示保存非托管資源的對象,但如果發現它們被放棄,它將從垃圾收集器接收通知(通過Finalize例程),並且將使用此類通知提供清理(​​如果在調用正常的清理方法之前它們被放棄了)。 有些人使用術語“托管資源”來指代不需要任何清理的東西,但我不喜歡這樣的用法,因為沒有任何其他好的術語來指代應該手動清理的東西但是將使用finalization作為后備,以防正常清理不發生。

請注意,雖然非托管資源通常是文件的OS句柄,GDI實體等,但用這樣的術語來思考它們是錯誤的。 可能有非托管資源不能訪問.Net框架之外的任何內容; 事件處理程序就是一個常見的例子。 非托管資源的關鍵方面是它們需要清理,而未能執行此類清理會產生一些不良后果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM