我在我正在处理的服务中间歇性地收到此错误
消息:System.IndexOutOfRangeException:索引超出了数组的范围。 在System.Collections.Generic.List
1.Enumerator.MoveNext() at System.Linq.Enumerable.<ExceptIterator>d__99
1.MoveNext() 在System.Linq.Enumerable.ElementAtOrDefault [TSource](IEnumerable`1 source,Int32 index)
代码如下所示:
List<ApplicationNames> originalApplicationNames = new List<ApplicationNames>(copyOfCachedVersions.Keys.ToList());
var exceptNames = applicationNames.Except( originalApplicationNames );
if (exceptNames != null && exceptNames.ElementAtOrDefault(0) != default(ApplicationNames))
基本上,if语句应该检查exceptNames是否有任何元素。我已经尝试过使用exceptNames.Count()&gt; 0和exceptNames.Any(),我得到相同的错误消息。我也试过了
var exceptNames = applicationNames.Except( originalApplicationNames ).ToList();
结果相同
我真的陷入了这一点,所以任何帮助都会非常感激!
答案 0 :(得分:4)
applicationNames
是一个静态对象,因此多个线程可以同时访问它。但是,存在锁定以防止它们同时修改它
当可以同时修改和读取集合时,仅防止并发修改是不够的。您需要防止与修改同时发生的读取,否则您会看到随机异常。
您可以通过复制applicationNames
:
private static IList<ApplicationNames> ApplicationNamesSync {
get {
// Use the same synchronization that prevents concurrent modifications
lock (appNamesLock) {
return applicationNames.ToList(); // Make a copy
}
}
}
现在您的代码将起作用:
List<ApplicationNames> originalApplicationNames = new List<ApplicationNames>(copyOfCachedVersions.Keys.ToList());
var exceptNames = ApplicationNamesSync.Except( originalApplicationNames );
if (exceptNames != null && exceptNames.ElementAtOrDefault(0) != default(ApplicationNames)) {
...
}