IDisposable,ObjectDisposedException和线程安全类型

时间:2010-02-11 18:28:58

标签: c# thread-safety idisposable objectdisposedexception

为了在所有主要暴露方法的开头有条件地抛出bool disposed,有没有必要跟踪线程安全类型上的经典ObjectDisposedException字段?

我已经在网上的几个地方看过这种模式,但我不确定作者是否正确使用它,所以这个问题假设它们是。

在这种情况下,似乎除了条件评估之外确保disposed条件为真的唯一方法是在每个公开成员的整个主体上使用锁定()等同步机制,包括Dispose(bool)方法。这不会使该类型再次有效地单线程吗?

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

====

我认为IDisposable和ObjectDisposedException不会一起用于线程安全类型。

4 个答案:

答案 0 :(得分:4)

在方法运行时,一种使线程安全对象不被处置的更有效方法是使用ReaderWriterLockSlim。让所有公共方法在执行时获得读锁定,并在完成后释放它。让Dispose获取作者锁。它会等到所有其他方法都完成后再获得写锁定。然后它将isDisposed设置在它独占的写锁定中。完成Dispose后对公共方法的任何调用都可以看到isDisposed并抛出ObjectDisposedException

<强> ReaderWriterLockSlim

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

答案 1 :(得分:3)

如果你的对象的行为已经被处理掉了,如果你的对象的行为很可能会在它被处理之后被使用,那么你需要跟踪它。抛出ObjectDisposedException比抛出任何随机异常更好,如果对象已经处理掉并且你没有先检查。

答案 2 :(得分:0)

鉴于“Disposed”布尔值仅在一个地方更新,并且调用者在调用Disposed之后使用该对象是一个错误。

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

答案 3 :(得分:0)

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