0

据我了解,使用DataContext并行工作不是线程安全的,但前提是您将上下文声明为static(基于 MSDN 文档)这就是我所做的,一旦我发现它有效,而另一次它失败了!

MSDN: 线程安全“这种类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。” http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx

似乎我遇到了与 Thread-Safety 相关的DataContext常见错误

在这里我解释一下我想做什么,我想要的结果是什么,希望得到专家的帮助和想法。

我想对大约 100,000 条记录进行繁重的分析,

错误是:

EntityMemberChanged 或 EntityComplexMemberChanged 是在没有首先在具有相同属性名称的同一更改跟踪器上调用 EntityMemberChanging 或 EntityComplexMemberChanging 的情况下调用的。有关正确报告更改的信息,请参阅实体框架文档。

指向设计器代码中的这一行:

            ReportPropertyChanged("ProductName");

我的代码中有什么:

    //On form Load
    if (Repository.ContextP == null)
          Repository.ContextP = new dbEntities();

    private void btnProcess_Click(object sender, EventArgs e)
    {
       Task.Factory.StartNew(() =>
         Process(), TaskCreationOptions.LongRunning); 
    }   

    private void Process()
    {
        var query = from W in Repository.ContextP.Products
                select W;

        Parallel.ForEach(query, options , product =>
        {
           // There are some heavy processes to get stFormattedDef
           product.ProductName= stFormattedDef;               
        }
     }

     // The Repository - static
     static class Repository
     {
         public static dbEntities ContextP { get; set; } 
     }

安全性和数据上下文生命周期应该不是问题,因为分析处于构建阶段并且是本地的。

我做错了什么?

有什么建议么?

类似案例的想法或经验?

4

1 回答 1

2

我不知道EF,但是从问题和评论来看,我认为问题在于你不能同时ProductName从不同的线程设置,即使是针对不同Product的s(因为它们都使用相同的非线程-安全DataContext)。

所以,我的建议是并行运行昂贵的操作,但要确保ProductName一次只从一个线程进行设置。实现这一目标的最简单方法是使用lock

var productLock = new object();

Parallel.ForEach(query, options , product =>
{
   // There are some heavy processes to get stFormattedDef

   lock (productLock)
   {
       product.ProductName = stFormattedDef;
   }
}

就像我说的,我不知道 EF,所以我不完全理解这个问题。因此,这可能不是正确的解决方案。

于 2012-06-24T16:06:22.683 回答