当您使用 ThreadLocal<T>
并且T
实现IDisposable时,应该如何处置ThreadLocal内部保留的成员?
根据ILSpy,ThreadLocal的Dispose()和Dispose(bool)方法是
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
int currentInstanceIndex = this.m_currentInstanceIndex;
if (currentInstanceIndex > -1 && Interlocked.CompareExchange(ref this.m_currentInstanceIndex, -1, currentInstanceIndex) == currentInstanceIndex)
{
ThreadLocal<T>.s_availableIndices.Push(currentInstanceIndex);
}
this.m_holder = null;
}
似乎ThreadLocal不会尝试对其子成员调用Dispose。我不知道如何引用它内部分配的每个线程,所以我可以照顾它。
我用以下代码运行了一个测试,该类从未被丢弃
static class Sandbox
{
static void Main()
{
ThreadLocal<TestClass> test = new ThreadLocal<TestClass>();
test.Value = new TestClass();
test.Dispose();
Console.Read();
}
}
class TestClass : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool Disposing)
{
Console.Write("I was disposed!");
}
}
最佳答案
我查看了ThreadLocal<T>
中的代码,以了解当前Dispose
的功能,这似乎是很多巫毒教徒。显然处理线程相关的东西。
但是,如果T
本身是一次性的,则不会处理这些值。
现在,我有一个解决方案-ThreadLocalDisposables<T>
类,但是在给出完整定义之前,值得考虑一下如果编写以下代码会发生什么:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>();
tl.Value = myEdr1;
tl.Value = myEdr2;
tl.Dispose();
应该同时处理
myEdr1
和myEdr2
吗?还是只是myEdr2
?还是应该在分配myEdr1
后处置myEdr2
?我不清楚语义应该是什么。
但是对我来说很明显,如果我编写了以下代码:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>(
() => new ExpensiveDisposableResource());
tl.Value.DoSomething();
tl.Dispose();
然后,我希望应该处理工厂为每个线程创建的资源。
因此,我将不允许直接为
ThreadLocalDisposables
分配一次性值,而仅允许工厂构造函数。这是
ThreadLocalDisposables
:public class ThreadLocalDisposables<T> : IDisposable
where T : IDisposable
{
private ThreadLocal<T> _threadLocal = null;
private ConcurrentBag<T> _values = new ConcurrentBag<T>();
public ThreadLocalDisposables(Func<T> valueFactory)
{
_threadLocal = new ThreadLocal<T>(() =>
{
var value = valueFactory();
_values.Add(value);
return value;
});
}
public void Dispose()
{
_threadLocal.Dispose();
Array.ForEach(_values.ToArray(), t => t.Dispose());
}
public override string ToString()
{
return _threadLocal.ToString();
}
public bool IsValueCreated
{
get { return _threadLocal.IsValueCreated; }
}
public T Value
{
get { return _threadLocal.Value; }
}
}
这有帮助吗?
关于c# - 处置ThreadLocal <IDisposable>中保存的元素的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7669666/