任务工厂和线程本地存储

时间:2014-01-24 17:20:17

标签: c# multithreading task-parallel-library task thread-local-storage

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

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

.Net中的ThreadLocal概念可能是这样的。

2 个答案:

答案 0 :(得分:5)

您不应该将ThreadLocal用于并行任务,如果您有需要处理的资源,除非您在创建对象时跟踪创建的对象,否则很难自行清理。这是因为在ThreadPool上创建了任务,因此无法保证再次返回同一个线程来进行清理工作 1

更好的方法是使用Parallel.ForParallel.ForEach接收lambda,该lambda创建一个与任务绑定的对象,并且一次只能被一个线程使用(命名为localInitlocalFinally)。

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属性,以便能够再次访问对象,而无需在创建时跟踪它们。

答案 1 :(得分:0)

一些想法:

  1. 在主进程中实例化ExpensiveObject的副本,然后让您的任务访问主副本(根据需要按值或引用)
  2. ExpensiveObject
  3. 使用静态类