任务工厂和线程本地存储

问题描述 投票:0回答:2

我在循环中从任务工厂创建 x 个任务。当我等待所有任务完成时,这些任务会开始执行一些工作。

我的问题是每个任务/线程都会初始化自己的昂贵对象(例如 DocumentObject)的副本。理想情况下,我希望为每个任务/线程重新使用这个对象,这样当它作为工厂的一部分重新使用时,就不需要重新创建。

.Net 中的

ThreadLocal
概念是否可以实现这样的事情。

c# multithreading task-parallel-library task thread-local-storage
2个回答
5
投票

您不应该将

ThreadLocal
与并行任务一起使用,如果您有需要处置的资源,则很难自行清理,除非您在创建对象时跟踪您创建的对象。这是因为任务是在线程池上创建的,因此无法保证再次返回同一线程来完成清理工作1

处理此问题的更好方法是使用

Parallel.For
Parallel.ForEach
,它接受一个 lambda,该 lambda 创建一个与任务绑定的对象,并且一次仅由一个线程使用(名为
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
属性,以便能够再次访问对象,而无需在创建对象时跟踪它们。


0
投票

一些想法:

  1. 在主流程中实例化
    ExpensiveObject
    的副本,然后让您的任务访问主副本(根据需要通过值或引用)
  2. 为您的
    ExpensiveObject
  3. 使用静态类
© www.soinside.com 2019 - 2024. All rights reserved.