题
我已经阅读了很多文章关于释放RCW的安全网,并在我看来,没有人能对需要什么样的顺序做什么同意,所以我要求你们为你们的意见。例如,一个可以这样做:
object target = null;
try {
// Instantiate and use the target object.
// Assume we know what we are doing: the contents of this try block
// do in fact represent the entire desired lifetime of the COM object,
// and we are releasing all RCWs in reverse order of acquisition.
} finally {
if(target != null) {
Marshal.FinalReleaseComObject(target);
target = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
不过,也有人主张做垃圾收集Marshal.FinalReleaseComObject
之前,一些后,有的根本没有。真的有必要手动GC每一个RCW,它已经从它的COM对象分离尤其是在?
在我看来,它会更简单,更容易刚刚从COM对象分离的RCW和离开RCW自然到期:
object target = null;
try {
// Same content as above.
} finally {
if(target != null) {
Marshal.FinalReleaseComObject(target);
}
}
是否足以做到这一点?
解决方案
要具有参考公布目标COM对象,它是足够的和优选以只是调用Marshal.FinalReleaseComObject
和不强>强制收集。换句话说,你见过你的责任,尽快释放你参考,你用它做。我不会碰FinalReleaseComObject
的问题VS ReleaseComObject
。
这留下的,为什么人主张调用GC.Collect()
和WaitForPendingFinalizers()
更大的问题?
由于一些设计中,这是很难知道什么时候有没有更多的托管引用,所以你不能安全地调用ReleaseComObject
。你有两个选择,让内存建立和希望付费的发生或强制收集。 [查看评论史蒂芬强森羽绒投票注意事项】
这是附加说明的是,设置target
到null
通常是不必要的,并且具体是在示例代码是不必要的。对象设置为Nothing是VB6常见的做法,因为它使用引用计数基于垃圾收集器。对于C#编译器足够聪明,甚至在离开之前范围(建设时释放)知道target
是其最后一次使用后,可达,可GC'd。而到最后使用,我的意思是最后可能使用所以有在那里你可以将其设置为null
案件。
using System;
class GCTest
{
~GCTest() { Console.WriteLine("Finalized"); }
static void Main()
{
Console.WriteLine("hello");
GCTest x = new GCTest();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("bye");
}
}
如果您构建释放(例如,CSC GCTest.cs),“结算”将打印出“你好”和“再见”之间。如果构建调试(例如,CSC /调试GCTest.cs),“结算”,将后“拜拜”,而设置x
为空,以Collect()
之前将有“固定”打印出。