C# 来自ThreadLocal的新值<;IDisposable>;在.Value.Dispose()之后

C# 来自ThreadLocal的新值<;IDisposable>;在.Value.Dispose()之后,c#,multithreading,idisposable,thread-local,C#,Multithreading,Idisposable,Thread Local,是否有一个内置的ThreadLocal类构造,用于在每个唯一线程内共享一个对象,但如果原始值被释放/破坏/删除/为空,则重新创建该对象 下面是我尝试使用concurrentdirectionary(下面的ThreadLocalDisposable2)实现这种行为的例子,但我希望只使用ThreadLocalDisposable1,但是我无法让Foo测试通过,值。删除(这个)没有达到我希望的效果,仍然会导致ObjectDisposedException public class Class1 {

是否有一个内置的
ThreadLocal
类构造,用于在每个唯一线程内共享一个对象,但如果原始值被释放/破坏/删除/为空,则重新创建该对象

下面是我尝试使用
concurrentdirectionary
(下面的
ThreadLocalDisposable2
)实现这种行为的例子,但我希望只使用
ThreadLocalDisposable1
,但是我无法让
Foo
测试通过,
值。删除(这个)
没有达到我希望的效果,仍然会导致
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();
    }
}
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();
    }
}
公共类ThreadLocalDisposable1:IDisposable
{
私人溪流(乌富);;
私有静态线程本地线程;
静态ThreadLocalDisposable1()
{
_thread=newthreadlocal(()=>newthreadlocaldisposable1(),true);
}
私有线程LocalDisposable1()
{
_foo=新内存流();
}
公共静态ThreadLocalDisposable1 Get()
{
返回_thread.Value;
}
公共图书馆
{
_foo.WriteByte(1);
}
公共空间处置()
{
//我不认为这意味着什么,我认为这意味着什么
_线程。值。删除(此);
_foo.Dispose();
}
}
[2]

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();
    }
}
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();
    }
}
公共类ThreadLocalDisposable2:IDisposable
{
私人溪流(乌富);;
私有int_线程;
私有静态ConcurrentDictionary_线程;
静态ThreadLocalDisposable2()
{
_线程=新的ConcurrentDictionary();
}
私有线程LocalDisposable2(int线程)
{
_螺纹=螺纹;
_foo=新内存流();
}
公共静态ThreadLocalDisposable2 Get()
{
返回_threads.GetOrAdd(Thread.CurrentThread.ManagedThreadId,i=>newthreadLocalDisposable2(i));
}
公共图书馆
{
_foo.WriteByte(1);
}
公共空间处置()
{
ThreadLocalDisposable2线程;
_threads.TryRemove(_thread,out thread);
_foo.Dispose();
}
}
编辑:

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

ThreadLocalDisposable1
[1],是我认为应该有效的示例类,除了
.Values之外。Remove(this)
行不会“使其停止流通”,而是强制为该线程创建一个新实例

ThreadLocalDisposable2
[2],以及
ConcurrentDictionary
,是我实现ThreadLocal的一种替代方法,我追求的是“退出流通”行为

编辑:


这不是一个真实的用例,只是一个我能想到的一般示例,但是如果您有一个静态
ThreadLocal
,或者一个套接字,并且它被强制关闭(并在最后一个块中处理)--删除该连接实例,并在再次调用时透明地创建一个新实例。

看起来您正在使这一过程变得更加困难。考虑这一点:

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>();
这在功能上似乎相当于您试图使用
ConcurrentDictionary
的东西


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

也许我没有想到,但您使用的是标记为threadlocal的concurrentdictionary吗?@daryal不,我使用的是它,而不是,请参见
ThreadLocalDisposable2
。我想使用
ThreadLocal
,但我不能完全让它工作,所以我有
ConcurrentDictionary
,它可以按照我的要求工作,但感觉有点黑客味。很难想象你在这里想做什么。不过,我建议您创建一个类,其中包含要使其成为可丢弃的对象,并创建该类的
ThreadLocal
实例。处理类内的处理/重新创建逻辑,而不是试图管理
ThreadLocal
实例的字典。@JimMischel请查看编辑,希望它现在更清晰一些。没有ThreadLocal实例字典。@IlyaKozhevnikov 1。编辑帖子通常比在评论中解释要好。2.你到底想做什么?这听起来是个很糟糕的主意…很有趣。。。具有非静态惰性“singleton”的由内而外的ThreadLocal。。。我没有那样想过。这并不理想,因为它公开了所有的
系统线程
内部,而不是对调用方完全透明。我会试一试,看看是否可以将其向后移植,谢谢。我是否正确理解它不是真正处理
MyClass
,只是交换了
,因此尽管在这个简化的示例中,
MyClass
有其他数据,例如写入流而不是1的实例字段,这将导致未指定的行为。所以我想说,它在功能上并不等同于
concurrentdirectionary
之类的东西。@IlyaKozhevnikov:不,它没有处理
MyClass
实例。这就是我的观点:创建一个持久性对象来包装一次性物品。@IlyaKozhevnikov
MyClass
只是一个包装器