C# 如何正确处置终结器中非托管资源的集合?
下面是一个我不确定的例子:C# 如何正确处置终结器中非托管资源的集合?,c#,.net,collections,dispose,idisposable,C#,.net,Collections,Dispose,Idisposable,下面是一个我不确定的例子: public class SomeClass : IDisposable { ~SomeClass() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private bool _disposed; protected virtual vo
public class SomeClass : IDisposable {
~SomeClass() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
// TODO: Release any managed resources here...
}
// ?! Is it safe to enumerate the dictionary here ?!
foreach (var resource in _resources.Values)
ReleaseBuffer(resource);
_resources = null;
_disposed = true;
}
}
private Dictionary<string, IntPtr> _resources;
...
}
public类SomeClass:IDisposable{
~SomeClass(){
处置(虚假);
}
公共空间处置(){
处置(真实);
总干事(本);
}
私人住宅;
受保护的虚拟void Dispose(bool disposing){
如果(!\u已处置){
如果(处置){
//TODO:在此处释放所有托管资源。。。
}
//?在这里列举字典安全吗?!
foreach(在_resources.Values中的var资源)
释放缓冲区(资源);
_资源=空;
_这是真的;
}
}
私人词典资源;
...
}
枚举托管字典以释放非托管资源是否安全
由于没有定义终结器的调用顺序,字典的可用性是否不确定
下面是一段摘自MSDN的引文,我觉得它让人困惑[1]:
- 即使一个对象引用另一个对象,也不能保证两个对象的终结器以任何特定顺序运行。也就是说,如果对象A引用了对象B,并且两者都有终结器,那么当对象A的终结器启动时,对象B可能已经被终结
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
您的示例显示如何释放条件块中的非托管资源。MSDN示例显示您应该释放条件块中的托管资源
正如它在文本中所说(在标题“Dispose(Boolean)重载”下):
如果方法调用来自终结器(即,如果disposing为false
),则只执行释放非托管资源的代码。由于未定义垃圾收集器在终结期间销毁托管对象的顺序,因此使用值false
调用此Dispose
重载可防止终结器尝试释放可能已回收的托管资源
与其拥有非托管资源的字典,不如建议拥有独立包装器对象的字典,每个包装器对象负责保护一个非托管资源。如果保存字典的对象被放弃,并且不存在对包装器对象的其他引用,那么所有包装器对象都将最终确定,而不需要让字典本身参与该过程。使用这种方法将更容易理智地处理在对象构造过程中发生异常的情况,并且至少在某种程度上理智地处理对象在排队等待终结和终结器运行期间发现自己复活的情况[代码通常不会运行]在这种情况下“正确”,但应避免破坏系统其余部分的状态]
例如,使用句柄的代码可能在使用期间获取锁,使用后检查“disposeObjectASAP”“国旗;如果已设置,请重新获取锁并释放对象。终结器本身应该设置标志,然后尝试获取锁;如果它成功地获取了锁,它应该处理该对象。如果不能,那么它设置标志的事实应该意味着拥有锁的代码注定要检查标志并清理对象,因此终结器不必这样做。如果终结器过早运行,它可能会释放另一个线程将需要的资源,导致该另一个线程上的操作失败,但终结器不会在另一个线程正在使用或处理资源时释放资源,因为在这些情况下释放资源可能会导致大量系统损坏。这应该是安全的,dictionary是以类实例为根的托管对象,在调用终结器之前,它是可访问的。请参阅。
字典
没有终结器。所以您是安全的。@Blorgbeard:Dictionary不是线程安全的,并且不能保证运行终结器的线程上下文。我的if(disposing)
语句中的注释纯粹是一个打字错误。但是访问\u资源
集合是有意的。为了将来的澄清,我已经纠正了我问题中的那个错误。谢谢