Parallel.Foreach中的同步锁定问题

本文关键字:锁定 问题 同步 Foreach Parallel | 更新日期: 2023-09-27 18:25:07

在过去的4年里,我一直在使用c#代码,但最近我遇到了一个从未经历过的场景。我有一个该死的项目来解决"索引超出范围错误"。代码看起来很疯狂,所有不必要的东西都在那里,但它已经生产了三年了,我只需要解决这个问题。问题来了。

class FilterCondition
{
   .....
   public string DataSetName {get; set;}
   public bool IsFilterMatch()
   {
      //somecode here
      Dataset dsDataSet = FilterDataSources.GetDataSource(DataSetName); // Static class and Static collection
      var filter = "columnname filtername"
      //some code here
      ds.defaultview.filter= filter;
      var isvalid = ds.defaultView.rowcount > 0? true : false;
      return isValid;
   }
}
// from a out side function they put this in a parallel loop
Parallel.ForEach()
{
   // at some point its calling
   item.IsFiltermatch();
}   

当我调试dsDataSet时,我看到dsDataSet修改了我的多个线程。这就是为什么出现竞争条件,并且它未能应用筛选器,并且索引超出范围时失败的原因。

我的问题是,我的方法是非静态和线程安全的,那么由于dsDataset是我的成员函数中的局部变量,这种竞争条件是如何发生的。奇怪,我怀疑和Parallel.Foreach有关。

当我把一个正常的锁放在那里时,问题得到了解决,对此我也没有答案。为什么要锁定非静态成员函数?

有人能给我一个答案吗。我是这个小组的新手。如果我在这个问题上遗漏了什么,请告诉我。由于那里有客户端限制,我无法复制整个代码。感谢阅读。

Parallel.Foreach中的同步锁定问题

因为它不是线程安全的
您正在从多个线程访问静态集合。

你对局部变量有误解。虽然变量是局部的,但它指向的对象不是局部的。

您应该做的是在静态集合的读写位置周围添加一个锁。

问题:问题存在于此调用中

FilterDataSources.GetDataSource(DataSetName);

在这个方法中,您正在向一个共享的资源进行写入。

解决方案:

你需要知道这里写的是哪个字段,并需要在它上实现锁定

注意:如果你能发布上面方法的代码,我们会更好地帮助你。

我相信这是因为FilterDataSources.GetDataSource(DataSetName)的特定(非无状态、非线程安全等)实现,即使通过方法调用,这似乎也是一个静态方法。这个方法可以做不同的事情,甚至可以返回缓存的DataSet实例,拦截对数据集项的调用,返回数据集包装器,这样你就可以使用包装器而不是数据集,所以可以有很多东西。如果你想细化,比如说导致这种情况的"确切代码行",请向我们展示GetDataSource()方法的实现和FilterDataSource类的所有底层静态上下文(静态字段、构造函数、GetDataSource()调用的其他静态方法,如果存在的话…)