gpt4 book ai didi

c# - 向 IDisposable 对象添加线程安全的正确方法是什么?

转载 作者:IT王子 更新时间:2023-10-29 04:14:36 24 4
gpt4 key购买 nike

想象一下 IDisposable 接口(interface)的实现,它有一些公共(public)方法。

如果该类型的实例在多个线程之间共享并且其中一个线程可能会处置它,那么确保其他线程在处置后不会尝试使用该实例的最佳方法是什么?在大多数情况下,对象被处置后,其方法必须知道它并抛出 ObjectDisposedExceptionInvalidOperationException 或至少通知调用代码做错了什么。我是否需要对每个 方法进行同步 - 特别是在检查它是否已被处置时?所有使用其他公共(public)方法的 IDisposable 实现都需要线程安全吗?


这是一个例子:

public class DummyDisposable : IDisposable
{
private bool _disposed = false;

public void Dispose()
{
_disposed = true;
// actual dispose logic
}

public void DoSomething()
{
// maybe synchronize around the if block?
if (_disposed)
{
throw new ObjectDisposedException("The current instance has been disposed!");
}

// DoSomething logic
}

public void DoSomethingElse()
{
// Same sync logic as in DoSomething() again?
}
}

最佳答案

您可以做的最简单的事情是将私有(private)处置变量标记为 volatile 并在您的方法开始时检查它。如果该对象已被处置,则您可以抛出 ObjectDisposedException

有两个注意事项:

  1. 如果方法是事件处理程序,则不应抛出 ObjectDisposedException。相反,如果可能的话,您应该优雅地退出该方法。原因是存在一种竞争条件,在您取消订阅后可以引发事件。 (有关更多信息,请参阅 Eric Lippert 的 this article。)

  2. 这不会阻止您的类在您正在执行其中一个类方法的过程中被释放。因此,如果您的类具有在处置后无法访问的实例成员,您将需要设置一些锁定行为以确保对这些资源的访问受到控制。

Microsoft 关于 IDisposable 的指南说您应该检查所有方法的处置情况,但我个人认为没有必要这样做。真正的问题是,如果您允许在处理类后执行方法,是否会引发异常或导致意外的副作用。如果答案是肯定的,您需要做一些工作以确保不会发生这种情况。

关于是否所有 IDisposable 类都应该是线程安全的:否。一次性类的大多数用例涉及它们只被单个线程访问。

话虽这么说,您可能想调查一下为什么需要您的一次性类是线程安全的,因为它增加了很多额外的复杂性。可能有一个替代实现,使您不必担心一次性类中的线程安全问题。

关于c# - 向 IDisposable 对象添加线程安全的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8927878/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com