dro*_*ron 16 c# idisposable thread-safety
当我查看示例实现时IDisposable,我还没有发现任何线程安全.为什么IDisposable没有实现线程安全?(相反,调用者有责任确保只调用一个线程Dispose()).
Ben*_*Ben 30
在完成对象之前,不应丢弃对象.如果有其他线程引用该对象,并且他们可能想要调用其方法,则不应该将其处理掉.
因此,Dispose不必是线程安全的.
线程安全的Dispose模式的唯一真正好处是可以保证在跨线程滥用的情况下获得ObjectDisposedException而不是潜在的不可预测的行为.请注意,这意味着该模式需要的不仅仅是线程安全的Dispose; 它要求所有依赖于未处置的类的方法与处理机制正确联锁.
这样做是可能的,但要覆盖仅在出现使用错误(即错误)时才会出现的边界情况需要付出很多努力.
Brian Lambert 撰写了一篇题为IDisposable 的简单且完全线程安全的实现的博客文章。
它包含以下实现:
using System;
using System.Threading;
/// <summary>
/// DisposableBase class. Represents an implementation of the IDisposable interface.
/// </summary>
public abstract class DisposableBase : IDisposable
{
/// <summary>
/// A value which indicates the disposable state. 0 indicates undisposed, 1 indicates disposing
/// or disposed.
/// </summary>
private int disposableState;
/// <summary>
/// Finalizes an instance of the DisposableBase class.
/// </summary>
~DisposableBase()
{
// The destructor has been called as a result of finalization, indicating that the object
// was not disposed of using the Dispose() method. In this case, call the DisposeResources
// method with the disposeManagedResources flag set to false, indicating that derived classes
// may only release unmanaged resources.
this.DisposeResources(false);
}
/// <summary>
/// Gets a value indicating whether the object is undisposed.
/// </summary>
public bool IsUndisposed
{
get
{
return Thread.VolatileRead(ref this.disposableState) == 0;
}
}
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with disposing of resources.
/// </summary>
public void Dispose()
{
// Attempt to move the disposable state from 0 to 1. If successful, we can be assured that
// this thread is the first thread to do so, and can safely dispose of the object.
if (Interlocked.CompareExchange(ref this.disposableState, 1, 0) == 0)
{
// Call the DisposeResources method with the disposeManagedResources flag set to true, indicating
// that derived classes may release unmanaged resources and dispose of managed resources.
this.DisposeResources(true);
// Suppress finalization of this object (remove it from the finalization queue and
// prevent the destructor from being called).
GC.SuppressFinalize(this);
}
}
#endregion IDisposable Members
/// <summary>
/// Dispose resources. Override this method in derived classes. Unmanaged resources should always be released
/// when this method is called. Managed resources may only be disposed of if disposeManagedResources is true.
/// </summary>
/// <param name="disposeManagedResources">A value which indicates whether managed resources may be disposed of.</param>
protected abstract void DisposeResources(bool disposeManagedResources);
}
Run Code Online (Sandbox Code Playgroud)
然而,绝对和完整的整体性在博客和此处的评论中都存在争议。