确定托管与非托管资源

有关托管与非托管资源的问题很多。 我理解这两者的基本定义。 但是,我很难知道资源或对象何时被管理或不受管理。

当我想到非托管资源时,我倾向于认为本机代码不是直接属于.NET的一部分,例如pinvoke或编组资源。 我通常认为资源意味着与使用硬件的东西接口,例如文件句柄或网络连接也是不受管理的。

那些包装本机非托管资源(如FileStream .NET对象呢?

FileStream必须使用非托管资源,但是当我实现IDisposable模式时,我应该将其视为托管或非托管资源吗?

到目前为止,我一直在假设如果对象实现了IDisposable ,那么它就被管理了。 我怎么知道IntPtr应该作为非托管resoruce处理?

FileStream必须使用非托管资源,但是当我实现IDisposable模式时,我应该将其视为托管或非托管资源吗?

FileStream是托管资源

托管资源是包含(并且必须管理)非托管资源的类。 通常,实际资源是几层。

到目前为止,我一直在假设如果对象实现了IDisposable ,那么它就被管理了。

正确。

我怎么知道IntPtr应该作为非托管resoruce处理?

从您获得其价值的API文档。 但请注意,在实践中,大多数程序员从不直接处理非托管资源。 当您必须时,使用SafeHandle类将非托管资源转换为托管资源。

它非常简单,您永远不会意外地分配非托管资源。 你需要一个pinvoke调用来分配它,你知道它。 术语“对象”被重载,但没有非托管对象,.NET程序中的所有对象都被管理。 您可以使用另一种支持创建对象的语言(如C ++)编写代码。 但是你不能直接使用这样的对象,需要C ++ / CLI包装器。 这使它成为实现IDisposable的托管类。

如果您使用记录不良的库,那么在获得IntPtr时请注意。 这是一个非常强烈的迹象,表明涉及非托管分配,指向非托管内存或操作系统句柄。 如果它不以其他方式自动管理它,那么该库也应该给你一种释放它的方法。 如果您不确定如何正确处理它,请与图书馆的所有者联系。

微软的工作是围绕所有常见的操作系统资源提供托管包装类。 像FileStream,Socket等。 这些类几乎总是实现IDisposable。 当您在自己的类中存储这样的类对象时,您在代码中唯一要做的就是自己实现IDisposable,这样就可以在这些对象上调用Dispose()方法。 如果将它们用作方法中的局部变量,请使用using语句。

在这种情况下,将“资源”视为“某个对象已经代表其他人做了其他事情,直到另行通知,对其他人有害”是最有帮助的。 如果放弃它会导致垃圾收集器通知放弃对象,则该对象构成“受管资源”,并且该对象反过来指示代表其行事的任何内容停止这样做。 “非托管资源”是未封装在托管资源中的资源。

如果某个对象Foo托管内存分配了一个句柄,它会要求内存管理器授予它对某些内存区域的独占使用权,使其对任何其他可能不想使用它的代码不可用,直到Foo通知内存为止。经理不再需要记忆,因此应该可以用于其他目的。 使句柄成为非托管资源的原因不在于它是通过API接收的,而是即使所有故意引用它都被放弃的事实,内存管理器将永远继续授予对象的独占使用权。更长的需求(可能不再存在)。

虽然API句柄是最常见的非托管资源,但也有无数其他类型。 监视器锁和事件之类的东西完全存在于.net的托管代码世界中,但是仍然可以表示非托管资源,因为在代码等待它时获取锁并放弃可能导致代码永远等待,并且因为短暂的生命从长期存在的对象订阅事件并且在被放弃之前未能取消订阅的对象可能导致该长期存在的对象无限期地继续携带事件引用(如果只有一个订阅者被放弃,则是一个小负担,但是无限制的负担如果创建并放弃了无限数量的订户)。

附录垃圾收集器的一个基本假设是,当对象X持有对象Y的引用时,这是因为X在Y中“感兴趣”。但是,在某些情况下,可能会保持引用,因为X希望Y持有引用尽管Y不会“关心”这种或那种方式。 通知事件处理程序经常发生这种情况。 每当对象X发生某些事情时,对象Y可能希望得到通知。虽然X必须保持对Y的引用以便它可以执行这样的通知,但X本身并不关心通知。 它只执行它们,因为假设一些有根的对象可能会关心Y接收它们。

在某些情况下,可以使用所谓的“弱事件模式”。 不幸的是,虽然.net中存在许多弱事件模式,但由于缺少适当的WeakDelegate类型,它们都有怪癖和局限性。 此外,虽然微弱事件是有帮助的,但它们并不是灵丹妙药。 例如,假设Y已经要求长期存在的对象X在发生某事时通知它,对Y的唯一现有引用是X用于此类通知的那个, Y对此类通知唯一做的就是增加属性。一些对象Z ,并设置该属性在Z之外修改任何内容。 在这种情况下,即使对象Z是宇宙中唯一“关心”对象YZ也不会对Y任何类型的引用,因此垃圾收集器将无法绑定Y ‘一生到Z的生命。 如果XY有强烈的引用,那么即使没有人对它感兴趣,后者也会保持活力。 如果X只持有弱引用,那么即使Z对它感兴趣, Y也可能被垃圾收集。 垃圾收集器没有机制可以自动推断ZY感兴趣。