处理时托管资源和本机资源有什么区别? (。净)

时间:2009-01-29 19:11:02

标签: .net resources native idisposable

我正在阅读MSDN article about how to implement IDisposable,我不确定文章中引用的托管资源和本机资源之间的区别。

我有一个类在处理它时必须处理它的两个字段。我应该将它们视为托管(仅在处置= true时处置)或本机资源吗?

3 个答案:

答案 0 :(得分:21)

为Brian的回答和你的评论/问题添加一点:

Managed / Unmanaged资源之间的区别在于垃圾收集器知道托管资源,并且不知道非托管资源。我知道答案不是很具体,但差别很大。

为了帮助在这里绘制线条,这是GC运行和清理内存的简短版本(可能还有很少的错误):

垃圾收集器知道所有托管对象,但是当垃圾收集运行时,它最初不知道任何给定对象是否仍在使用中或者是否可以被释放。它通过最初将所有对象标记为垃圾,然后从应用程序根遍历到所有引用的对象来确定它是否可以清理对象。具有回到根的关系的每个对象(引用,直接或间接)被标记为可达,并且不再被视为垃圾。 GC运行每个可到达的对象后,它会清理其余的,因为它们不再使用。

在使用.NET框架对象的几乎所有情况下,都可以确保管理对象(.NET提供几乎所有非托管资源的托管包装,以确保它们得到正确清理);挂钩到Win32 API(或执行此操作的组件)的其他第三方组件是可能引起关注的对象。

有些.NET对象可以被认为是有些不受管理的。图形库的组件就是一个例子。

大多数“.NET内存泄漏”并不是真正意义上的内存泄漏。通常,当您认为已删除某个对象时,它们会发生,但实际上该对象仍然具有对该应用程序的一些引用。一个常见的例子是添加事件处理程序(obj.SomeEvent + = OnSomeEvent -or-AddHandler obj.SomeEvent,AddressOf OnSomeEvent)而不删除它们。

这些“挥之不去的引用”在技术上并非内存泄漏,因为您的应用程序仍在技术上使用它们;但是,如果有足够的应用程序,您的应用程序可能会受到严重的性能影响,并可能出现资源问题的迹象(OutOfMemoryExceptions,无法获得窗口句柄等)。

我是一名中级.NET开发人员,不幸的是他第一时间了解这些问题。我建议使用ANTS Profiler来帮助熟悉延迟引用(有一个免费试用版),或者如果你想通过WinDbg和SOS.DLL来查看托管堆,可以进行更多细节研究。如果您决定研究后者,我建议您阅读Tess Ferrandez的博客;她有很多很好的教程和有效使用Windbg的建议

答案 1 :(得分:19)

托管资源是另一种托管类型,它实现IDisposable。您需要在您使用的任何其他Dispose()类型上致电IDisposable。本机资源是托管世界之外的任何内容,例如本机Windows句柄等。


编辑:在评论中回答问题(评论时间过长)

不,这只是一种托管类型。正确构造的类型(未实现IDisposable)将由垃圾收集器处理,您不必执行任何其他操作。如果您的类型直接使用本机资源(例如,通过调用Win32库),则必须在类型上实现IDisposable并在Dispose方法中处置资源。如果您的类型使用由实现IDisposable的其他类型封装的本机资源,则必须在类型的Dispose()方法中对此类型的实例调用Dispose

答案 2 :(得分:1)

简短的回答是你在CLR背后(到操作系统)获得的任何东西都可以被称为'原生'。

  • 非托管内存分配。如果你在托管类CantStayManaged中“新”了一大块内存,那么CantStayManaged负责释放这个内存(资源)。
  • 处理文件,管道,事件,同步构造等 - 如果您调用WinAPI来获取资源的指针/句柄,则作为拇指规则,那些是“本机资源”

所以现在,CantStayManaged在出价之前需要清理2件事。

  1. 托管:成员字段和CLR分配的任何资源。这通常等同于在“一次性”成员对象上调用Dispose。
  2. 不受管理:我们背后的所有鬼鬼祟祟的低级别东西。
  3. 现在有两种方法可以触发对象清理。

    1. Dispose(true)case:您在类型上明确调用了Dispose。优秀的程序员。
    2. Dispose(false)case:你忘了调用Dispose,在这种情况下终结器应该启动并仍然确保正确清理。
    3. 在这两种情况下,非管理资源应该被释放,否则“泄漏!”,“崩溃!”等表面。 但是,您应该只尝试在Dispose()以前的情况下清理托管资源。 在后者/终结器的情况下 - CLR可能已经完成并收集了一些成员,因此您不应该访问它们(CLR不保证最终确定对象图的顺序。)因此,您可以避免出现问题使用if (AmIBeingCalledFromDispose)警卫检查进行管理清理

      HTH