我编写了一个包含非托管C ++对象的托管类,但我发现 - 在C#中使用它时 - 在我对对象执行方法时,GC会提前启动。我已经阅读了垃圾收集以及如何防止垃圾收集提前发生。一种方法是使用“using”语句来控制何时放置对象,但这会将责任放在托管对象的客户端上。我可以添加到托管类:
MyManagedObject::MyMethod()
{
System::Runtime::InteropServices::GCHandle handle =
System::Runtime::InteropServices::GCHandle::Alloc(this);
// access unmanaged member
handle.Free();
}
System::Runtime::InteropServices::GCHandle handle =
System::Runtime::InteropServices::GCHandle::Alloc(this);
// access unmanaged member
handle.Free();
这似乎有效。作为.NET的新手,其他人如何处理这个问题?
谢谢,
约翰
答案 0 :(得分:3)
您可能希望看一下这篇文章:http://www.codeproject.com/Tips/246372/Premature-NET-garbage-collection-or-Dude-wheres-my。我相信它完全描述了你的情况。简而言之,补救措施是using
阻止或GC.KeepAlive
。但是,我同意在许多情况下,您不希望将此负担传递给非托管对象的客户端;在这种情况下,在每个包装器方法结束时调用GC.KeepAlive(this)是一个很好的解决方案。
答案 1 :(得分:2)
如果要保持终结器不被调用,可以在方法体中使用GC.KeepAlive(this)
。正如其他人在评论中正确指出的那样,如果在方法调用期间您的this
引用不存在,则可以调用终结器并在调用期间回收内存。
有关详细的案例研究,请参阅http://blogs.microsoft.co.il/blogs/sasha/archive/2008/07/28/finalizer-vs-application-a-race-condition-from-hell.aspx。