我在循环中从任务工厂创建了 x 个任务。当我等待所有任务完成时,这些任务会停止并做一些工作。
我的问题是每个任务/线程都会初始化自己的一个昂贵对象的副本,比如 DocumentObject。理想情况下,我希望为每个任务/线程重新使用此对象,这样当它作为工厂的一部分重新使用时,就无需重新创建。
.Net 中的ThreadLocal
概念是否可以实现类似的功能。
最佳答案
你不应该使用 ThreadLocal
对于并行任务,如果您有需要处理的资源,则很难自己清理,除非您在创建对象时跟踪您创建的对象。这是因为任务是在 ThreadPool 上创建的,所以无法保证再次回到同一个线程上进行清理工作1。
处理此问题的更好方法是使用 Parallel.For
或 Parallel.ForEach
它接受一个 lambada,该 lambada 创建一个与任务相关的对象,并且一次仅由一个线程使用(名为 localInit
和 localFinally
)。
Parallel.ForEach(GetSomeData(), () => new DocumentObject(),
(sourceData, loopState, localData)
{
//localData is the DocumentObject that unique per thread.
//...
return localData; //Passes the class to the next task that is going to use it.
}
(localData) =>
{
localData.Dispose(); //Do any work here you need to do when a thread is done with the object.
}
当然,如果您在localFinally
中没有任何工作要做,请继续使用ThreadLocal
,如果您愿意的话。
1:他们在 4.5 中新增了 Values
属性,以便能够再次访问对象,而无需在创建对象时对其进行跟踪。
关于c# - 任务工厂和线程本地存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21338612/