.net - Dispose 方法的线程安全性?

标签 .net thread-safety dispose idisposable

MSDN 很好地记录了 BCL 类型的实例成员的线程安全性,但我从未真正见过说明如何调用 IDisposable 类型的 Dispose 方法的信息.

Dispose 方法是否 a) 保证对所有类都是线程安全的,b) 从不保证是线程安全的,c) 保证对某些类是线程安全的(如果是的话) ,具体记录在哪里)?

最后,如果保证 Dispose 方法是线程安全的,这是否意味着我必须在使用一次性资源的类中的每个实例方法上加锁?

旁白:我知道类型的终结器应该是线程安全的,因为垃圾收集在 .NET 中的工作方式(相当激进),并且它们可能会调用 Dispose 方法。不过,我们先把这个问题放在一边。

最佳答案

线程安全和Dispose的问题有些棘手。由于在许多情况下,一旦任何其他线程开始处置对象,任何线程可以合法地对对象做的唯一事情就是尝试处置它本身,因此乍一看似乎确保线程安全所需的唯一事情是在“dispose”标志上使用 Interlocked.Exchange,以确保一个线程的 Dispose 尝试发生,而另一个线程被静默忽略。事实上,这是一个很好的起点,我认为它应该是标准 Dispose 模式的一部分(CompareExchange 应该在密封的基类包装方法中完成,以避免每个派生类都需要使用自己的私有(private)已处置标志)。不幸的是,如果考虑一下 Dispose 实际做了什么,事情就会复杂得多。

Dispose 的真正目的不是对正在处置的对象执行某些操作,而是清理该对象所引用的其他实体。这些实体可能是托管对象、系统对象或完全其他的东西;它们甚至可能与被处置的对象不在同一台计算机上。为了使 Dispose 成为线程安全的,那些其他实体将允许 Dispose 在其他线程可能对它们执行其他操作的同时清理它们。有些对象可以处理这种用法;其他人则不能。

一个特别令人烦恼的例子:对象被允许拥有带有非线程安全的RemoveHandler方法的事件。因此,任何清理事件处理程序的 Dispose 方法都只能从与创建订阅的线程相同的线程中调用。

关于.net - Dispose 方法的线程安全性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5024883/

相关文章:

java - 多个线程同时共享同一个函数

multithreading - 这是初始化 [ThreadStatic] 的线程安全方式吗?

c# - 使用 Ninject 的 Dapper 一次性实例

c# - WinForms 和处理自定义控件

javascript - js dataTable yadcf 保留过滤器值

c# - ASP.NET MVC 6 基于 HTTP 状态码处理错误

.net - StopWatch.ElapsedTicks 和 StopWatch.Elapsed.Ticks 总是一样的吗?

Java - 当子线程因 NPE 死亡时会发生什么,父线程是否会被杀死

c# - Aforge.net 相机捕获并将图像保存到目录

c# - ServicePointManager.FindServicePoint 的用途是什么?