New value from ThreadLocal<IDisposable> after .Value.D

本文关键字:gt after Value IDisposable lt value from ThreadLocal New | 更新日期: 2023-09-27 18:10:10

是否有一个内置的ThreadLocal<T>类结构共享对象在每个唯一的线程,但重新创建它,如果原始值被处置/销毁/撕下/空?

这是我在ConcurrentDictionary(下面的ThreadLocalDisposable2)实现这种行为的尝试,但我希望只是使用ThreadLocal<T>(如ThreadLocalDisposable1),但是我不能得到Foo测试通过,.Values.Remove(this)不做我希望它会做的事情,仍然导致ObjectDisposedException

public class Class1
{
    [Test]
    public void Foo()
    {
        using (var foo = ThreadLocalDisposable1.Get())
            foo.Foo();
        using (var foo = ThreadLocalDisposable1.Get())
            foo.Foo();
    }
    [Test]
    public void Bar()
    {
        using (var bar = ThreadLocalDisposable2.Get())
            bar.Foo();
        using (var bar = ThreadLocalDisposable2.Get())
            bar.Foo();
    }
}

[1]

public class ThreadLocalDisposable1 : IDisposable
{
    private Stream _foo;
    private static ThreadLocal<ThreadLocalDisposable1> _thread;
    static ThreadLocalDisposable1()
    {
        _thread = new ThreadLocal<ThreadLocalDisposable1>(() => new ThreadLocalDisposable1(), true);
    }
    private ThreadLocalDisposable1()
    {
        _foo = new MemoryStream();
    }
    public static ThreadLocalDisposable1 Get()
    {
        return _thread.Value;
    }
    public void Foo()
    {
        _foo.WriteByte(1);
    }
    public void Dispose()
    {
        //I do not think it means what I think it means
        _thread.Values.Remove(this);
        _foo.Dispose();
    }
}

[2]

public class ThreadLocalDisposable2 : IDisposable
{
    private Stream _foo;
    private int _thread;
    private static ConcurrentDictionary<int, ThreadLocalDisposable2> _threads;
    static ThreadLocalDisposable2()
    {
        _threads = new ConcurrentDictionary<int, ThreadLocalDisposable2>();
    }
    private ThreadLocalDisposable2(int thread)
    {
        _thread = thread;
        _foo = new MemoryStream();
    }
    public static ThreadLocalDisposable2 Get()
    {
        return _threads.GetOrAdd(Thread.CurrentThread.ManagedThreadId, i => new ThreadLocalDisposable2(i));
    }
    public void Foo()
    {
        _foo.WriteByte(1);
    }
    public void Dispose()
    {
        ThreadLocalDisposable2 thread;
        _threads.TryRemove(_thread, out thread);
        _foo.Dispose();
    }
}
编辑:

只是为了澄清我的意思,基本上我想要ThreadLocal的所有行为,但是当我调用Dispose时(在这个例子中,ThreadLocalDisposable*在这个例子中具有底层Stream,而不是静态ThreadLocal本身),将处置的实例从循环中取出,即如果再次调用-创建一个新值,就好像它是一个全新的线程需要一个全新的实例。

ThreadLocalDisposable1[1],是我认为应该工作的样例类,除了.Values.Remove(this)行没有"将其从循环中取出"并强制为该线程创建一个新实例。

ThreadLocalDisposable2[2]ConcurrentDictionary一起,是我实现ThreadLocal的替代方法,具有我所追求的"退出循环"行为。

编辑:

这不是一个真正的用例我有,只是一个一般的例子,我能想到的,但如果你有一个静态的ThreadLocal<SqlConnection>,或套接字,它被强制关闭(并处置在最后块)-删除该连接实例,并创建一个新的透明,如果再次调用

New value from ThreadLocal<IDisposable> after .Value.D

看起来你把这件事弄得比本来更困难了。想想看:

public class MyClass: IDisposable
{
    private Stream _foo;
    public MyClass Get()
    {
        if (_foo == null)
        {
            _foo = new MemoryStream();
        }
    }
    public void Foo()
    {
        _foo.WriteByte(1);
    }
    public void Dispose()
    {
        if (_foo != null)
        {
            _foo.Dispose();
            _foo = null;
        }
    }
}

现在,您可以创建其中一个:

ThreadLocal<MyClass> MyThing = new ThreadLocal<MyClass>();

你可以写:

using (MyThing.Value.Get())
{
    // do stuff
}

这似乎在功能上等同于你试图用ConcurrentDictionary做的事情。

也就是说,这似乎是另一种更好的管理方式。我不知道你的应用程序,所以我不能肯定地说,但它似乎是一个坏主意,有一个有状态的对象,如StreamSqlConnection作为一个全局变量。通常这些东西是特定于作业的,而不是特定于线程的,因此应该在启动作业时作为参数传递。