C# 任务工厂和线程本地存储

C# 任务工厂和线程本地存储,c#,multithreading,task-parallel-library,task,thread-local-storage,C#,Multithreading,Task Parallel Library,Task,Thread Local Storage,我在一个循环中从任务工厂创建x个任务。当我等待所有任务完成时,这些任务开始并完成一些工作 我的问题是,每个任务/线程都初始化自己的昂贵对象副本,比如DocumentObject。理想情况下,我希望为每个任务/线程重新使用这个对象,这样当它作为工厂的一部分重新使用时,就不需要重新创建 在.Net中的ThreadLocal概念中可能出现这种情况。您不应该将其用于并行任务,如果您有需要处理的资源,则很难自行清理,除非您在创建时跟踪创建的对象。这是因为任务是在线程池上创建的,因此无法保证再次回到同一线程

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

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

在.Net中的
ThreadLocal
概念中可能出现这种情况。

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

处理此问题的更好方法是使用或,它接受一个lambada,该lambada创建一个绑定到任务的对象,并且一次仅由一个线程使用(名为
localInit
localFinally

当然,如果您在
localFinally
中没有任何工作要做,请继续使用
ThreadLocal


1:4.5版新增了属性,以便能够再次访问对象,而无需在创建对象时跟踪它们。

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

处理此问题的更好方法是使用或,它接受一个lambada,该lambada创建一个绑定到任务的对象,并且一次仅由一个线程使用(名为
localInit
localFinally

当然,如果您在
localFinally
中没有任何工作要做,请继续使用
ThreadLocal


1:4.5版新增了该属性,以便能够再次访问对象,而无需在创建对象时跟踪对象。

一些想法:

  • 在主流程中实例化
    ExpensiveObject
    的副本,然后让您的任务访问主副本(根据需要通过值或引用)
  • 为您的
    ExpensiveObject使用静态类
  • 一些想法:

  • 在主流程中实例化
    ExpensiveObject
    的副本,然后让您的任务访问主副本(根据需要通过值或引用)
  • 为您的
    ExpensiveObject使用静态类

  • 你不能在启动并行循环之前实例化一个DocumentObject吗?但是该对象跨线程不安全。你不能在启动并行循环之前实例化一个DocumentObject吗?但是该对象跨线程不安全。是的。。我怀疑“昂贵的对象”是否有足够的线程安全性来使用一个静态。。我怀疑“昂贵的对象”是否有足够的线程安全性来使用一个静态线程。
    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.
        }