2009-01-29 82 views

回答

18

托管资源是另一种托管类型,它实现了IDisposable。您需要在您使用的任何其他IDisposable类型上致电Dispose()。原生资源是管理世界以外的任何东西,例如原生Windows处理等


编辑:答案在评论的问题(太长评论)

不,这仅仅是一个管理型。一个正确构造的类型,不会实现IDisposable将由垃圾收集器处理,你不必做任何事情。如果您的类型直接使用本地资源(例如,通过调用Win32库),则必须在您的类型上实现IDisposable,并在Dispose方法中处理资源。如果您的类型使用由实现IDisposable的另一种类型封装的本地资源,则必须在类型的Dispose方法中针对此类型的实例调用Dispose()

+0

所以是不实现IDisposable的非托管资源的托管型?也许我被类型诗歌资源困惑... – 2009-01-29 20:49:45

+0

@Yooder:你怎么能有一个托管资源,而不是一个类型代表? – 2009-04-23 03:32:07

+0

@LarryFix:不同的人使用不同的术语,但我会说,一个没有要求*别的东西*代表它做某件事情的对象,直到进一步的通知,并损害他人,并不成立*任何*资源。 – supercat 2012-12-12 16:20:31

21

要一点点增加Brian的回答,您的评论/问题:

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

为了帮助划清界线在这里的沙子是如何GC运行的短期(可能有一点差错百出)版和清理内存:

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

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

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

大多数“.NET内存泄漏”实际上并不是真正的内存泄漏。通常他们发生在你认为认为你已经从使用中移除了一个对象但实际上该对象仍然有一些对该应用程序的引用。一个常见的例子是添加事件处理程序(obj.SomeEvent + = OnSomeEvent - 或 - AddHandler obj.SomeEvent,AddressOf OnSomeEvent)并且不删除它们。

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

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

1

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

  • 非托管内存分配。如果您在托管类CantStayManaged中创建了大量内存,则CantStayManaged负责释放此内存(资源)。
  • 处理的文件,管道,事件,同步构造等 - 作为一个经验法则,如果你打电话WinAPIs获得指针/句柄的资源,那么那些“本土资源”

所以现在CantStayManaged有两件事情需要在投标前进行清理。

  1. 托管:成员字段和CLR分配的任何资源。这通常等同于在'Disposable'成员对象上调用Dispose。
  2. 非托管:我们背后所有低级的东西。

现在有两种方法可以触发对象清理。

  1. Dispose(true)case:您明确地在您的类型上调用Dispose。好的程序员。
  2. Dispose(false)case:您忘记了调用Dispose,在这种情况下,终结器应该启动并仍然确保正确清理。

在这两种情况下,非托管资源都应该被释放,否则'泄漏!','破坏!'等表面。 但是,您应该只尝试在Dispose()前一种情况下清理受管资源。 在后者/终结器的情况下 - CLR可能已经完成并收集了一些您的成员,因此您不应该访问它们(CLR不能保证对象图的定单顺序)。守着你的管理清理与if (AmIBeingCalledFromDispose)警卫检查

HTH