【发布时间】:2016-01-22 16:10:51
【问题描述】:
我注意到 MSDN (like this one) 上有一些课程有一个 Disposing 事件并带有以下评论:
在调用 Dispose 时或当垃圾收集器最终确定并收集此对象时发生。
我想在我的一个班级中实现我自己的Disposing 事件。这是我的基本实现(following the best practices for the dispose pattern):
public abstract class Handle : IDisposable
{
public bool Disposed { get; private set; }
public event System.Action DisposingCompleted;
public Handle()
{
Disposed = false;
}
~Handle()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing = false)
{
if (Disposed)
{
return;
}
if (disposing)
{
HandleManagedResources();
}
HandleUnManagedResources();
Disposed = true;
if (DisposingCompleted != null)
{
DisposingCompleted();
}
}
protected virtual void HandleManagedResources() {}
protected virtual void HandleUnManagedResources() {}
}
有人在我的代码审查中提到,他们不确定触发这样的事件是否安全,因为 Dispose() 可能会从终结器中调用,但是根据我在该 MSDN 链接上添加的 cmets顶部,很明显有对象在 Disposed OR Finalized 时触发事件。
是我遗漏了什么还是安全? GraphicsDevice 如何实现从 dispose 或最终确定时触发的事件?如果答案只是“不,你永远不能这样做”,那么还有其他方法可以达到同样的效果吗? (对象被释放的事件OR已完成)
【问题讨论】:
-
您应该使用标准建议的实现和模式,例如命名和约定,而不是自己滚动。特别是,您应该使用
bool disposing而不是bool fromFinalizer。 -
@LasseV.Karlsen 当然,我改了名字。
-
您可能想阅读 Eric Lipperts 的帖子,了解终结器ericlippert.com/2015/05/18/… 中可能发生的所有怪异现象@
-
从不,从不在 disposing 为 false 时引发事件。你不能让终结器运行任意代码,它不会导致问题的几率非常低。 Disposing 事件只有在你有足够的保证 Dispose() 方法将被调用时才是合理的。这往往很难实现。除非类对象完全在你的控制之下。
-
@HansPassant
GraphicsDevice如何实现一个事件,该事件可以在处置或完成时触发?它由微软实现;我想如果它有问题会被注意到。
标签: c# events garbage-collection dispose idisposable