如何重新创建“索引超出数组范围”将项目添加到字典?

Posted

技术标签:

【中文标题】如何重新创建“索引超出数组范围”将项目添加到字典?【英文标题】:How to recreate "Index was outside the bounds of the array" adding items to Dictionary? 【发布时间】:2012-09-26 17:30:10 【问题描述】:

我一直在多线程 .net 3.5 应用程序上收到此错误

错误 26 抛出异常。详细信息:'System.IndexOutOfRangeException:索引超出范围 数组。

at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)

在 System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)

我想我知道如何修复它(在适当的地方添加锁),但我希望能够在我的本地环境中重新创建这个问题,所以我会确保我修复了它并且我能够添加对其进行单元测试。

你知道任何一致的方法来重新创建这个吗?

【问题讨论】:

您不使用 ConcurrentDictionary 是否有特殊原因? @Sconibulus:这个应用是3.5,不能用ConcurrentDictionary :( 【参考方案1】:
Dictionary<string, string> dict = new Dictionary<string, string>();

Task.Factory.StartNew(() =>  while (true) dict["a"] = "a"; );
Task.Factory.StartNew(() =>  while (true) dict.Remove("a"); );

【讨论】:

是的,这会导致字典错误,但取决于正在运行的 OP 代码的其余部分和他提出的解决方案,这并不完全有帮助。 有了这段代码,我完全可以重现问题,不幸的是,我的真实代码不能说同样的话。将问题标记为已解决,因为我认为这是我能得到的最好的结果,而无需投入数百行代码。谢谢!【参考方案2】:

不幸的是,在发生竞争条件的多线程应用程序中保持一致是根本无法实现的。

您的机器和生产机器之间的硬件差异将确保当问题确实发生时,它可能不在同一个位置。即使硬件相同,软件差异(尤其是那些后台服务)也会导致时间差异,从而导致无法重复的情况。

哎呀,如果这些线程依赖于外部资源(如数据库调用),那么生产和测试盒之间的网络延迟差异可能会确保您永远无法复制它。

不愿在服务器上安装调试器(坏主意),您可以做的最好的事情是对代码进行可视化分析,修复您认为需要修复的部分,对其进行测试(尽可能地)然后发布并在生产中观看。

【讨论】:

【参考方案3】:

这不会帮助您在本地重新创建错误,但要完全消除错误,通用 Dictionary<TKey, TValue> 的 msdn 文档说:

有关线程安全的替代方案,请参阅ConcurrentDictionary<TKey, TValue>。

ConcurrentDictionary<TKey, TValue> 的文档说:

表示一个线程安全的键值对集合,可以 多个线程同时访问。

但请注意,ConcurrentDictionary 仅在 .Net 4 及更高版本中可用。

【讨论】:

我的应用是3.5,不能使用ConcurrentDictionary :(【参考方案4】:

为什么不为字典创建一个包装器,其中包含 ReaderWriterLockSlim。这样,您就可以在一个班级中完成所有锁定。

【讨论】:

以上是关于如何重新创建“索引超出数组范围”将项目添加到字典?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复此 System.IndexOutOfRangeException:索引超出数组范围

获取“索引超出数组范围”异常

转换向量索引超出数组边界 - matlab

如何将项目添加到字典“并行循环安全”

将对象添加到 JSONKit 创建的字典?

如何将重复键添加到字典中