GarbageCollector使成员字段无效
本文关键字:无效 字段 成员 GarbageCollector | 更新日期: 2023-09-27 18:09:15
我正在调试一些c#类(比如Foo),它实现了Dispose- finalize模式,也就是说,如果Dispose还没有被调用,它的Finalizer会调用Dispose()。
在Dispose()中有访问Foo的某些成员的日志代码(假设是Bar)。Bar也是某种引用类型的实例,是只读的(在Foo的构造函数中创建),并且不暴露在Foo之外的任何地方。因此,在Foo的垃圾收集时,Bar很可能也已经被收集了。理论上说,这样的成员字段不应该从Finalize线程访问。
但是日志代码不知道理论,并试图记录一些酒吧的属性。并且进程在终结器线程中因NullReferenceException而崩溃。
我明白当你忽略理论时可能会发生不好的事情,但我没有预料到NRE:垃圾收集器是否将对收集对象的引用设置为null?还是我遗漏了什么?
在实现Dispose方法时,他们特别注意从终结器访问其他对象。这就是为什么它们有这样的模式:
~MyObject()
{
Dispose(false); // False because it's being called in a finalizer
}
public void Dispose()
{
Dispose(true); // True because it was called from user code
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// here it's safe to access other CLR objects
}
// Here you dispose of any unmanaged objects
}
如果你偏离了这种模式——特别是当终结器调用Dispose
并试图访问其他可能已经被处置的对象时,你就会遇到问题。
还请注意,除非创建一个分配非托管资源的类,否则不需要终结器。如果你的类只使用CLR对象或提供。net对象的第三方库,那么就不需要终结器了。