Sco*_*ain 25 c# idisposable .net-4.0 thread-local
当你使用a 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;
}
Run Code Online (Sandbox Code Playgroud)
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!");
}
}
Run Code Online (Sandbox Code Playgroud)
Eni*_*ity 12
我看了一下代码,ThreadLocal<T>
看看目前的情况Dispose
是什么,看起来很多伏都教.显然处理与线程相关的东西.
但如果T
它本身是一次性的,它不会处置这些值.
现在,我有一个解决方案 - 一个ThreadLocalDisposables<T>
类,但在我给出完整的定义之前,值得考虑如果你编写这个代码会发生什么:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>();
tl.Value = myEdr1;
tl.Value = myEdr2;
tl.Dispose();
Run Code Online (Sandbox Code Playgroud)
都应该myEdr1
与myEdr2
同时配置?还是只是myEdr2
?或者myEdr1
在myEdr2
分配时应该处理?
我不清楚语义应该是什么.
但是,我很清楚,如果我写了这段代码:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>(
() => new ExpensiveDisposableResource());
tl.Value.DoSomething();
tl.Dispose();
Run Code Online (Sandbox Code Playgroud)
然后我希望工厂为每个线程创建的资源应该被处理掉.
所以我不会允许直接分配一次性值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; }
}
}
Run Code Online (Sandbox Code Playgroud)
这有帮助吗?
在 .NET 4.5 中,Values属性被添加到 ThreadLocal<> 以处理手动管理 ThreadLocal 对象的生命周期的问题。它返回绑定到该 ThreadLocal 变量的所有当前实例的列表。
这篇 MSDN 文章中提供了一个使用 Parallel.For 循环访问 ThreadLocal 数据库连接池的示例。相关代码片段如下。
var threadDbConn = new ThreadLocal<MyDbConnection>(() => MyDbConnection.Open(), true);
try
{
Parallel.For(0, 10000, i =>
{
var inputData = threadDbConn.Value.GetData(i);
...
});
}
finally
{
foreach(var dbConn in threadDbConn.Values)
{
dbConn.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4967 次 |
最近记录: |