0

在我的程序中System.ArgumentException,尝试使用该AddRange功能时遇到了未处理的问题:

目标数组不够长。检查 destIndex 和长度,以及数组的下限。

调试时,我打破了我的行的异常:

ListA.AddRange(ListB);

在调试器的监视工具中,我可以看到:

ListA: Count = 2454
ListB: Count = 0

查看通用列表的文档ArgumentException,未列出。

在试图查明到底出了什么问题时,我是否遗漏了什么?

4

2 回答 2

1

List<T>不是线程安全的。从文档

线程安全

此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。不保证任何实例成员都是线程安全的。

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

从多个线程同时写入 a 或在另一个线程上读取时在一个线程上写入a是不安全的。您将看到随机的“无法解释的”异常,就像您所看到的那样。List<T>List<T>

使用锁来正确同步对列表的访问、使用线程安全集合或重新架构,这样您就不需要这样做了。

于 2019-11-08T16:16:26.930 回答
0

编辑:不要介意我的帖子的其余部分。这是一个比赛条件。这显然发生在最后的 AddRange 部分。显然,在增长步骤和实际副本期间,任一数组的大小都不同。而到了这样的程度,内部阵法还不够壮大

一个简单的锁块覆盖任一阵列上的所有写入工作应该可以解决这个问题。

原始答案 - 可以忽略

你的标题解释了它。你得到一个参数异常,因为你试图将一个空列表添加到现有列表中。根据 AddRange() 函数的设计者,这不是一个有效的操作。

ArgumentException的用途非常狭窄:

当提供给方法的参数之一无效时引发的异常。

当调用方法并且至少有一个传递的参数不符合被调用方法的参数规范时,将引发 ArgumentException。ParamName 属性标识无效参数。

由于它有一个目的,因此对于每个函数调用中可能发生的每种情况都不需要特别提及。事实上,你应该被鼓励自己扔掉它。

为避免这种情况,请不要将空列表输入 AddRange()。检查以下内容将是微不足道的:

if(ListB.Lent > 0){
  ListA.AddRange(ListB);
}

由于您提供了有关如何创建 ListB 的 0 信息,因此我们无法告诉您为什么此时它有时为空。它只是并且很容易检查。

我使用这两篇​​文章作为我的异常处理的基础:

这个异常很简单,是一个Boneheaded Exception 的例子。空列表有一个远程参数不是那么特殊。然而,AddRange() 的设计者认为它足以保证例外。使用基本 if 也可以轻松避免,因此不能真正将其归类为 Vexing Exception。因此,即使经过所有考虑,它仍然只是一个 Boneheaded 例外。请停止造成它。

于 2019-11-08T15:56:46.220 回答