2012-03-30 65 views
5

我使用这里描述的管理处置模式: http://www.developerzen.com/2006/01/09/finalizableobject-developing-a-base-class-for-idisposable-objects/在一次性模式中什么是“非托管资源”?

为真正重要的“非托管资源?”

这里有一些令人困惑的点在我的脑海:

  • 在某一点上,.NET只是包装Win32调用,对不对?那么,大多数.NET对象是不是非托管资源?
  • 怎么样我们有.NET包装的COM对象 - 他们考虑了什么?
  • 那些只能从P/Invokes获取功能的托管类呢?
  • 内部使用本地库的C++/CLI类如何?在C#级别,具有析构函数的C++/CLI类现在实现了IDisposable ...他们考虑了什么?

我意识到博客文章有点旧。如果有更现代的管理未管理和管理对象的生命周期的方式,请提出建议。

编辑:无论谁投票关闭此,请提供一些细节,我如何可以改善问题。

+0

*“如果有更新的方法来解决这个问题......”*这里的问题究竟是什么? – 2012-03-30 19:38:44

+0

管理非托管和管理对象的生命周期。如果以错误的顺序执行此操作,则可能发生死锁 – jglouie 2012-03-30 19:40:13

+0

[文档](http://msdn.microsoft.com/library/System.IDisposable.aspx)中给出的示例有什么问题? – 2012-03-30 19:41:28

回答

7

我理解的混乱。我觉得有一些简单的指导遵循:

  1. 如果你的类“拥有”到另一个对象的引用(即你的对象创建的其他物体,或给予与理解参照该对象你的对象现在“拥有”它),那么你有责任做任何必要的清理(如果有的话)

  2. 如果那个其他对象是一个.NET对象并且没有实现IDisposable接口,那么你可能不需要需要做任何事情。按照惯例,IDisposable接口是我们用来声明我们的对象是否需要清理的接口。

  3. 如果那个其他对象是一个.NET对象并实现了IDisposable接口,那么你的类也应该实现IDisposable接口。在您的Dispose方法中,只需调用另一个对象的Dispose方法即可。

  4. 如果其他对象是非托管对象或资源,那么您的类应实现终结器以确保非托管对象/资源将被清理。遵循该博客文章中介绍的指导原则,了解如何实施该指南。

下面是对您的问题的一些具体答案。

  • 在某些时候,.NET只是包装Win32调用,对吧?那么,大多数.NET对象是不是非托管资源?

即使.NET对象可以包装Win32调用,因为它是一个.NET对象的术语“非托管资源”是不恰当的,因此它是由定义中的“管理资源”。 CLR处理这些对象的内存分配和垃圾收集。

  • 怎么样我们有.NET包装器的COM对象 - 他们考虑了什么?

.NET包装的对象仍然是.NET对象,所以他们是“管理资源”,但请注意,必须实现自己的物/敲定逻辑。基本上,他们负责清理“非托管资源”,这样你就不必担心了。如果你正在为COM对象实现自己的包装器,那么你将负责实现必要的dispose/finalize逻辑来清理它,以便包装器的用户不必这样做。

  • 那些只从P/Invokes获得功能的托管类呢?

一个管理使用的P/Invoke调用非托管代码可能会被分配非托管资源,这取决于它被调用的类。因此,它可能需要实施必要的处理/定稿逻辑来清理那些非托管资源。

  • 如何在内部使用本地库的C++/CLI类?

是的,这些也可以从本地库被分配非托管资源,所以它也有必要对他们实施必要的析构函数/终结逻辑。

  • 在C#的水平,即有现在的析构函数实现IDisposable的C++/CLI类......被他们认为是什么?

在C++/CLI中,可以选择将声明一个类如任一管理(与ref关键字)或非托管(没有ref关键字)。如果使用ref关键字声明它,那么它是一个托管类;它将被分配到托管堆上,并在垃圾收集器超出范围并且没有更多引用时被垃圾收集器清理。如果该类没有使用ref关键字声明,那么它是非托管的,必须明确清理。无论哪种情况,该类可能都分配了需要在析构函数/终结器中清理的非托管资源。

+0

非常感谢你解决子弹 - 这真的为我清除了概念。 – jglouie 2012-03-30 20:21:07

0

首先想到的是,.net之外的任何东西都是非托管资源。被管理对象是.net字符串,数组,值类型和由它们组成的复杂类型,所有这些对象都被管理并且它们的生命周期由.net自动控制。字符串不是一个包装物,所以它是完全管理的。

大多数.NET基类都是从头开始编写的,比如List,Stack等,我们可以简化说任何对象及其后代只是引用堆栈中的数据或者堆被管理。

任何其他打开的连接/句柄访问堆栈/堆外的任何内容都是非托管的,无论是文件,命名管道,网络还是任何设备。

大多数其他BCL类都进行了优化,但除非您使用block将它们包装在一起,否则它们将不会自动按其写入方式自动处理。

1

这里是我当作 “非托管”(注意引号):

  1. 凡是实现了IDisposable。如果它想要被处置...呃,相信它。不管它是纯粹的“安全”.NET还是实现一个空的Dispose方法。为了处理它与一次性模式,它是“非托管”。
  2. 任何COM RCW。这方面有很多争论, I view each COM->NET RCW count-increase as "owned" and thus "unmanaged"最终 RCW将在析构函数中自行清理,但在处理Outlook对象模型时,“最终”会导致很多问题,这与我一起工作。这种方法需要一致的方法来处理COM对象和生命周期,以避免“RCW分离”问题。
  3. 任何[new] 资源通过P/Invoke调用(如BSTR)获得:分配所述资源“拥有”它直到控制权被放弃为止。这确实是一个“非托管”资源,必须予以释放。对于可以分配的各种资源,有一些有用的包装类型。

我不对付非COM本地代码(例如CLI),除了少数WinAPI的电话,这些都是C.

相关问题