C# IDisposable、ObjectDisposedException和threadsafe类型

C# IDisposable、ObjectDisposedException和threadsafe类型,c#,thread-safety,idisposable,objectdisposedexception,C#,Thread Safety,Idisposable,Objectdisposedexception,为了在所有主要公开方法的开头有条件地抛出ObjectDisposedException,跟踪其他线程安全类型上的经典bool disposed字段有何意义 我在网上的一些地方看到过推荐的这种模式,但我不确定作者是否正确使用了它,所以这个问题假设他们是正确的 在这样的场景中,似乎确保disposed条件在条件的计算之外为真的唯一方法是在每个公开成员(包括Dispose(bool)方法)的整个主体上使用诸如lock()的同步机制。这不会使类型有效地再次单线程吗 如果这是真的,那么使用它就没有意义了,

为了在所有主要公开方法的开头有条件地抛出
ObjectDisposedException
,跟踪其他线程安全类型上的经典
bool disposed
字段有何意义

我在网上的一些地方看到过推荐的这种模式,但我不确定作者是否正确使用了它,所以这个问题假设他们是正确的

在这样的场景中,似乎确保
disposed
条件在条件的计算之外为真的唯一方法是在每个公开成员(包括Dispose(bool)方法)的整个主体上使用诸如lock()的同步机制。这不会使类型有效地再次单线程吗

如果这是真的,那么使用它就没有意义了,因此在一些IDisposable实现中不能依赖ObjectDisposedException机制——那么,如果没有必要,我们为什么要使用这种机制呢

====


我猜IDisposable和ObjectDisposedException对于线程安全类型来说并不一致。

也许在方法运行时使线程安全对象不被释放的更有效方法是使用
ReaderWriterLockSlim
。让所有公共方法在执行时获得一个读锁,并在完成后释放它。让
Dispose
获得写入程序锁。它将等待所有其他方法完成后,才能获得写锁。然后将
isDisposed
设置在其独占持有的写锁内。完成
Dispose
后对公共方法的任何调用都可以查看
isDisposed
并抛出
ObjectDisposedException

ReaderWriterLockSlim


如果对象已被处置,其行为将有所不同,并且可能在处置后使用,则需要跟踪此情况。抛出
ObjectDisposedException
比抛出任何随机异常要好,如果对象已经被释放,并且您没有先检查,那么将发生任何随机异常。

因为“disposed”布尔值只在一个位置更新,并且调用方在调用disposed后使用该对象是一个错误


我认为在调用Dispose之后“大部分时间”抛出ObjectDisposedException已经足够了。我认为ObjectDisposedException是一个调试助手,而不是调用方应该捕获的东西。

如果在对象被释放时有可能调用一个方法,那么该方法的语义应该以这样一种方式定义,即在被释放的对象上调用它不会引起任何问题。在可能存在或不存在问题的情况下,应该使用“尝试/做”模式。如果微软在Control.BeginInvoke上遵循了这一原则,那么就会有“Control.BeginInvoke”和“Control.TryBeginInvoke”;后者将被显式定义为返回false,如果在操作进入队列之前释放了控件,则不执行任何操作(请注意,返回true的control.BeginInvoke不能保证在操作实际运行之前不会释放该控件)。这种模式在显示更新场景中非常有用:如果控件未被释放,我希望它的更新例程运行;但是,如果它在更新例程运行之前被处理掉,那么更新将变得毫无意义,它的运行失败几乎不会是一个问题。

Cool idea。有样品吗?在ReaderWriterSlimLock上找不到文档。这是你以前见过的还是你刚刚头脑风暴的东西?只是头脑风暴,但我认为它应该适合你的要求。我在原始答案中拼错了,它是
readerwriterlocksim
。我添加了一个指向MSDN文档的链接。实际上,除了FXcop正确地指出ReaderWriterLockSlim实现了IDisposable,应该与对象的其余资源一起处理外,这几乎是可行的。因此,一旦调用了处理,我就不能再获得一个读锁来测试对象是否已经被丢弃。我不认为这个问题是关闭的,但是这是一个很好的尝试,我不想让这个问题公开。但这个问题是关于如何在多线程场景中确定地抛出ObjectDisposedException。