2014-10-01 81 views
0

我创建了一个包含堆对象的存储器持有者类,并且我想 确定该对象的配置对于GC非常有用。是否可以确定在最后一个对象引用释放之后正好放置的对象?

我想是这样的:

myObj = null; //Immediately call to ~myObj() 
+0

终结器没有确定性地调用。你可以用GC.Collect强制一个GC,但这会迫使GC运行 - 这是一个陡峭的惩罚 - 不这样做(我把它提出来,因为有人可能会推荐它)。它甚至不保证你已经设法删除对象的所有强引用。你试图做的是对付.NET Framework的一些设计哲学。我会试着找出一种遵循这些哲学的方法,而不是对付它们。 – vcsjones 2014-10-01 17:35:45

+0

我可以创建一个COM对象吗?是否是IUnknown.Release在最后强调的参考去掉了? – 2014-10-01 17:37:32

+0

我知道,但我在一个小型库中创建我的Memory类,供初学者使用,我希望他们对内存垃圾回收没有任何帮助。 – 2014-10-01 17:38:43

回答

2

.NET框架和运行时为使用非托管资源的应用程序提供了两个功能。

  1. 确定性清理:该IDisposable接口允许代码在特定的时间释放资源,通过显式或隐式地调用Dispose()方法。 (C#中的using声明提供了这一呼吁隐性支持。)
  2. - 最终清理:在活动用户无法通过调用Dispose()方法来释放非托管资源,一个终结可以用来防止漏水长时间运行的应用程序随着时间的推移,用户代码通常不应包含用户定义的终结器;相反,创建(或使用现有的)类扩展了SafeHandle并实现了ReleaseHandle方法来定义发布行为。

注意IDisposable.Dispose()是确定性资源清理只有支持的机制。最终的清理是应该避免的非确定性回退。

2

不,你不能做到这一点。你应该简单地使用IDisposable,因为它意味着使用。

+0

好吧,我明白了! ,但我可以创建一个COM对象吗? IUnknown.Release()在最后一次被强调的引用中被删除了吗? – 2014-10-01 17:42:38

+0

我对COM对象不太熟悉,但我认为你可以在你的Dispose方法中调用'IUnknown.Release()'。使用'Dispose(bool)'方法注意http://msdn.microsoft.com/en-us/library/system.idisposable.aspx中托管资源和非托管资源的模式。 – 2014-10-01 17:48:21

0

COM对象希望在超出范围时及时通知,但.NET不支持除Dispose之外的即时通知。您应该在处理方法中调用IUnknown.Release,但在调用IUnknown.Release之前必须确保任何人都不会再尝试再次使用该COM对象。试图使用Release之后的COM对象,或者仅仅试图再次拨打Release,这是一种灾难。

因此,我建议不要将COM对象本身的引用释放给外部代码。相反,让持有对象的所有对象在锁中向对象本身发送所有请求(以确保代码不会尝试同时访问),并让您的方法获取锁,请在对象上调用Release,然后使用使参考无效。任何未来试图操作没有被捕获的对象都会导致NullReferenceException这不是很好,但仍然比在发布后尝试使用对象更好。