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有关。
当我把一个正常的锁放在那里时,问题得到了解决,对此我也没有答案。为什么要锁定非静态成员函数?
有人能给我一个答案吗。我是这个小组的新手。如果我在这个问题上遗漏了什么,请告诉我。由于那里有客户端限制,我无法复制整个代码。感谢阅读。
因为它不是线程安全的
您正在从多个线程访问静态集合。
你对局部变量有误解。虽然变量是局部的,但它指向的对象不是局部的。
您应该做的是在静态集合的读写位置周围添加一个锁。
问题:问题存在于此调用中
FilterDataSources.GetDataSource(DataSetName);
在这个方法中,您正在向一个共享的资源进行写入。
解决方案:
你需要知道这里写的是哪个字段,并需要在它上实现锁定
注意:如果你能发布上面方法的代码,我们会更好地帮助你。
我相信这是因为FilterDataSources.GetDataSource(DataSetName)
的特定(非无状态、非线程安全等)实现,即使通过方法调用,这似乎也是一个静态方法。这个方法可以做不同的事情,甚至可以返回缓存的DataSet
实例,拦截对数据集项的调用,返回数据集包装器,这样你就可以使用包装器而不是数据集,所以可以有很多东西。如果你想细化,比如说导致这种情况的"确切代码行",请向我们展示GetDataSource()
方法的实现和FilterDataSource
类的所有底层静态上下文(静态字段、构造函数、GetDataSource()
调用的其他静态方法,如果存在的话…)