Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 删除项目时出现Task Parallel.ForEach循环错误";索引超出了数组的边界&引用;_C#_Task Parallel Library - Fatal编程技术网

C# 删除项目时出现Task Parallel.ForEach循环错误";索引超出了数组的边界&引用;

C# 删除项目时出现Task Parallel.ForEach循环错误";索引超出了数组的边界&引用;,c#,task-parallel-library,C#,Task Parallel Library,我试图删除foreach循环中对象的通用列表中的项。当我对任务并行库循环做同样的事情时,我得到了错误。 索引超出了数组的边界。 下面是我的代码 List<string> lstSubscriberDidTransaction = ...; // Initialization var lstSubscriber = JsonConvert.DeserializeObject<List<SubscriberInfoShortenObject>>(somestrin

我试图删除foreach循环中对象的通用列表中的项。当我对任务并行库循环做同样的事情时,我得到了错误。 索引超出了数组的边界。

下面是我的代码

List<string> lstSubscriberDidTransaction = ...; // Initialization
var lstSubscriber = JsonConvert.DeserializeObject<List<SubscriberInfoShortenObject>>(somestring);

foreach (string strId in lstSubscriberDidTransaction)
{
    lstSubscriber.RemoveAll(h => h != null && h.Msisdn == strId);
}

//Parallel.ForEach(lstSubscriberDidTransaction, msisdn => lstSubscriber.RemoveAll(h => h != null && h.Msisdn == msisdn));
List lstSubscriberDidTransaction=…;//初始化
var lstSubscriber=JsonConvert.DeserializeObject(somestring);
foreach(lstSubscriberDidTransaction中的字符串strId)
{
lstSubscriber.RemoveAll(h=>h!=null&&h.Msisdn==strId);
}
//Parallel.ForEach(lstSubscriberDidTransaction,msisdn=>lstSubscriber.RemoveAll(h=>h!=null&&h.msisdn==msisdn));
有人能帮我吗
我正在使用.NET3.5。对于具有

的任务并行库,
列表
类不是为并发写入(/remove)操作而设计的,如中所述:

对一个列表执行多个读取操作是安全的,但是 如果在读取集合时对其进行修改,则可能会出现问题。 为确保线程安全,请在读取或写入期间锁定集合 活动使集合能够由多个线程访问 对于读写,您必须实现自己的同步。 有关内置同步的集合,请参见中的类 System.Collections.Concurrent命名空间。对于固有的线程安全性 或者,请参见ImmutableList类

有关支持并发访问的数据结构,请参阅

要澄清问题产生于
列表
类的原因,请执行以下操作:
RemoveAll
操作将在列表实例上迭代,并根据包含的每个实例匹配谓词。如果谓词的计算结果为true,则匹配实例的索引将用于删除条目。如果操作是在并发事件中执行的,那么另一个线程可能已经删除了另一个条目,因此索引不再有效,或者将指向与谓词不匹配的另一个实例。因此,该操作不是线程安全的,不会给出您期望的结果。 为了便于查看,给定的代码是
列表
类中的反编译方法:

public int RemoveAll(Predicate<T> match)
{
  if (match == null)
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
  int index1 = 0;
  while (index1 < this._size && !match(this._items[index1]))
    ++index1;
  if (index1 >= this._size)
    return 0;
  int index2 = index1 + 1;
  while (index2 < this._size)
  {
    while (index2 < this._size && match(this._items[index2]))
      ++index2;
    if (index2 < this._size)
      this._items[index1++] = this._items[index2++];
  }
  Array.Clear((Array) this._items, index1, this._size - index1);
  int num = this._size - index1;
  this._size = index1;
  ++this._version;
  return num;
}
public int RemoveAll(谓词匹配)
{
if(match==null)
ThrowHelper.ThrowArgumentNullException(argument.match除外);
int index1=0;
而(index1=该尺寸)
返回0;
int index2=index1+1;
而(index2<此尺寸)
{
而(index2

要提供更多提示,请执行以下操作: 不要使用并行代码,因为如果没有大的更改,它将不会帮助您。优化查找数据结构并简化语句

HashSet<string> lstSubscriberDidTransaction = ...
...

lstSubscriber.RemoveAll(h => h != null && lstSubscriberDidTransaction.Contains(h.Msisdn))
HashSet lstSubscriberDidTransaction=。。。
...
lstSubscriber.RemoveAll(h=>h!=null&&lstSubscriberDidTransaction.Contains(h.Msisdn))

这将提高性能,要获得更多帮助,我们需要对您的代码有更多的了解。

您可以尝试
Parallel.ForEach(lstSubscriberDidTransaction.ToArray())
他似乎在迭代两个不同的源。
lstSubscriberDidTransaction
lstSubscriber
RemoveAll
也会迭代列表,所以
lstSubscriber
他是以并行方式读写的。@KamranShahid不要使用并行代码,因为它对您的情况没有帮助。只需调用
lstSubscriber.RemoveAll(h=>h!=null&&lstSubscriberDidTransaction.Contains(h.Msisdn))
@KamranShahid优化数据结构,查看我的更新答案。问题查看了1000多次,但有人对其进行了负面标记。我希望当有人否决投票时,应该有必要的评论,以便提问者能够了解其中的错误。