什么是添加线程安全到了IDisposable对象的正确方法是什么? [英] What is the correct way of adding thread-safety to an IDisposable object?

查看:133
本文介绍了什么是添加线程安全到了IDisposable对象的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下,一个实施的IDisposable 的接口,有一些公共的方法。

如果该类型的实例,多线程和一个线程可以处理这之间共享,哪些是为了保证其他线程不要试图用实例来处理工作后最好的方法是什么?在大多数情况下,该对象被设置后,它的方法必须意识到这一点,并抛出了的ObjectDisposedException 或者 InvalidOperationException异常或者至少告知调用$ C $下做错了什么。我是否需要同步进行的每次方式 - 尤其是周围的检查,如果它被设置?是否所有的IDisposable 的实施与其他公共方法必须是线程安全的?


下面是一个例子:

 公共类DummyDisposable:IDisposable的
{
    私人布尔_disposed = FALSE;

    公共无效的Dispose()
    {
        _disposed = TRUE;
        //实际处置逻辑
    }

    公共无效DoSomething的()
    {
        //也许同步,如果各地块?
        如果(_disposed)
        {
            抛出新的ObjectDisposedException(目前情况下已被释放!);
        }

        // DoSomething的逻辑
    }

    公共无效DoSomethingElse()
    {
         //相同的同步逻辑在DoSomething的()了吗?
    }
}
 

解决方案

你可以做最简单的事情是标志着民营处置变量挥发性并在开始检查它你的方法。然后,您可以抛出一个的ObjectDisposedException 如果该对象已被释放。

有两个警告这样:

  1. 您应该不会引发的ObjectDisposedException ,如果该方法是一个事件处理程序。相反,你应该刚刚摆好的方法退出,如果这是可能的。的原因是,存在在那里的活动后,可以从他们退订提高竞争状态。 (见通过这篇文章埃里克利珀以获取更多信息。)

  2. 这不被处理,而你在执行你的类方法之一的中间停止你的类。所以,如果你的类具有无法处置后访问实例成员,你将需要设置一些锁定行为,以确保获得这些资源的控制。

周围的IDisposable微软的指引说,你应该检查设置在所有方法,但我还没有亲自找到这个必要。真正的问题是,是什么将抛出一个异常,导致意外的副作用,如果你让一个方法来执行的类配置后。如果答案是肯定的,你需要做一些工作,以确保不会发生。

在所有IDisposable的类是否应该是线程安全的条款:不可以。大多数用例一次性类涉及他们永远只能由一个线程访问。

话虽这么说,你可能要调查为什么你需要你的一次性类是线程安全的,因为它增加了很多额外的复杂性。有可能是另一种实现,它可以让你不必担心线程安全问题,在您的一次性类。

Imagine an implementation of the IDisposable interface, that has some public methods.

If an instance of that type is shared between multiple threads and one of the threads may dispose it, what is the best way to ensure the other threads do not attempt to work with the instance after disposed? In most cases, after the object is disposed, its methods must be aware of it and throw the ObjectDisposedException or maybe InvalidOperationException or at least inform the calling code for doing something wrong. Do I need synchronization for every method - particularly around the check if it is disposed? Do all IDisposable implementations with other public methods need to be thread-safe?


Here is an example:

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?
    }
}

解决方案

The simplest thing you can do is mark the private disposed variable as volatile and inspect it at the beginning of your methods. You can then throw an ObjectDisposedException if the object has already been disposed.

There are two caveats to this:

  1. You shouldn't throw an ObjectDisposedExceptionif the method is an event handler. Instead you should just gracefully exit from the method if that is possible. The reason being is that there exists a race condition where events can be raised after you unsubscribe from them. (See this article by Eric Lippert for more information.)

  2. This doesn't stop your class from being disposed while you are in the middle of executing one of your class methods. So if your class has instance members that can't be accessed after disposal, you're going to need to setup some locking behaviour to ensure access to these resources are controlled.

Microsoft's guidance around IDisposable says you should check for disposed on all methods, but I haven't personally found this necessary. The question really is, is something going to throw an exception or cause unintended side effects if you allow a method to execute after the class is disposed. If the answer is yes, you need to do some work to make sure that doesn't happen.

In terms of whether all IDisposable classes should be thread safe: No. Most of the use cases for disposable classes involve them only ever being accessed by a single thread.

That being said, you may want to investigate why you need your disposable class to be thread safe as it adds a lot of additional complexity. There may be an alternate implementation that allows you to not have to worry about thread safety issues in your disposable class.

这篇关于什么是添加线程安全到了IDisposable对象的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆