.NET GC删除正在使用的对象

tde*_*may 1 c# garbage-collection

我遇到了一个问题,它会出现GC线程正在唤醒并删除正在使用的对象.

当processfoo正在运行时,在它返回之前,它会出现fooCopy析构函数在一个单独的线程中触发.有没有人看到这样的问题,如果是这样,你如何解决它?当然,这不可能真的发生,我必须做错事.谁能给我一些调试垃圾收集的提示/策略?

try
{
    CFoo fooCopy = new CFoo(someFoo);
    someBar.ProcessFoo(fooCopy);
}
Run Code Online (Sandbox Code Playgroud)

CFoo有一个IntPtr成员变量.ProcessFoo将该成员变量传递给C++ DLL中的导入函数,该函数可能需要几秒钟才能运行.

在我的C++ DLL中,我在创建IntPtr时以及删除它时记录,我可以在ProcessFoo运行时看到一个单独的线程删除IntPtr.

Ser*_*rvy 5

当然,这不可能真的发生,我必须做错事.

不,它绝对可能发生(这就是为什么写终结器很难,你应该尽可能地避免它们,并且在被迫写它们时要非常小心).一旦运行时可以证明没有代码会再次尝试访问它,就可以对对象进行GC编辑.如果调用实例方法(并且在调用之后的任何时间都不会访问对象实例),则该对象在上次使用this该实例方法后立即有资格进行收集.

范围内的对象(例如,this方法的变量)但在该范围内从未再次使用的对象不被GC视为根.

至于你如何解决它,如果你有一个你想要被认为是"活着"的变量,即使它从未在托管代码中再次访问过,请使用GC.KeepAlive.在这种情况下,将GC.KeepAlive(this)在2002年底ProcessFoo将确保有问题的对象保持活着直到方法结束(或者,如果它不是方法的责任,有主叫电话GC.KeepAlive(someBar)之后ProcessFoo).

有关主题的更多信息,以及终结器的一些相关甚至更不寻常的属性,请参阅此博客文章.