我正在阅读MSDN article about how to implement IDisposable,我不确定本文引用的托管资源和本地资源之间的差异。处置时托管资源与本地资源有什么区别? (.NET)
我有一个类,它必须在处理它的两个字段时处置。我应该将它们视为托管(仅在处置= true时配置)还是本机资源?
我正在阅读MSDN article about how to implement IDisposable,我不确定本文引用的托管资源和本地资源之间的差异。处置时托管资源与本地资源有什么区别? (.NET)
我有一个类,它必须在处理它的两个字段时处置。我应该将它们视为托管(仅在处置= true时配置)还是本机资源?
托管资源是另一种托管类型,它实现了IDisposable
。您需要在您使用的任何其他IDisposable
类型上致电Dispose()
。原生资源是管理世界以外的任何东西,例如原生Windows处理等
编辑:答案在评论的问题(太长评论)
不,这仅仅是一个管理型。一个正确构造的类型,不会实现IDisposable
将由垃圾收集器处理,你不必做任何事情。如果您的类型直接使用本地资源(例如,通过调用Win32库),则必须在您的类型上实现IDisposable
,并在Dispose
方法中处理资源。如果您的类型使用由实现IDisposable
的另一种类型封装的本地资源,则必须在类型的Dispose
方法中针对此类型的实例调用Dispose()
。
要一点点增加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的建议
简短的回答将是任何你在CLR的背后(到操作系统)获取可以被称为'原生'。
所以现在CantStayManaged有两件事情需要在投标前进行清理。
现在有两种方法可以触发对象清理。
在这两种情况下,非托管资源都应该被释放,否则'泄漏!','破坏!'等表面。 但是,您应该只尝试在Dispose()前一种情况下清理受管资源。 在后者/终结器的情况下 - CLR可能已经完成并收集了一些您的成员,因此您不应该访问它们(CLR不能保证对象图的定单顺序)。守着你的管理清理与if (AmIBeingCalledFromDispose)
警卫检查
HTH
所以是不实现IDisposable的非托管资源的托管型?也许我被类型诗歌资源困惑... – 2009-01-29 20:49:45
@Yooder:你怎么能有一个托管资源,而不是一个类型代表? – 2009-04-23 03:32:07
@LarryFix:不同的人使用不同的术语,但我会说,一个没有要求*别的东西*代表它做某件事情的对象,直到进一步的通知,并损害他人,并不成立*任何*资源。 – supercat 2012-12-12 16:20:31