Linq.Enumerable的界外索引 [英] Index Out of Bounds in Linq.Enumerable
问题描述
我在我正在使用的服务中间歇性地收到此错误
I've been getting this error intermittently in a service I'm working on
消息:System.IndexOutOfRangeException:索引超出数组的范围.在System.Collections.Generic.List
1.Enumerator.MoveNext()在System.Linq.Enumerable中.< ExceptIterator> d__99
1.MoveNext()在System.Linq.Enumerable.ElementAtOrDefault [TSource](IEnumerable`1源,Int32索引)
Message: System.IndexOutOfRangeException: Index was outside the bounds of the array. at System.Collections.Generic.List
1.Enumerator.MoveNext() at System.Linq.Enumerable.<ExceptIterator>d__99
1.MoveNext() at 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语句应该检查exceptionNames是否包含任何元素.我已经尝试过使用exceptionNames.Count()> 0和exceptionNames.Any(),并且得到相同的错误消息.我也尝试过
Basically, the if statement is supposed to check if exceptNames has any elements. I've already tried using exceptNames.Count() > 0 and exceptNames.Any(), and I get the same error message. I've also tried
var exceptNames = applicationNames.Except( originalApplicationNames ).ToList();
结果相同
我现在真的很困,所以任何帮助将不胜感激!
I'm really stuck at this point, so any help would be greatly appreciated!
推荐答案
applicationNames
是一个静态对象,因此多个线程可以同时访问它.但是,这里有锁定功能以防止他们同时修改它
applicationNames
is a static object, so several threads would have access to it simultaneously. However, there is locking in place to prevent them from modifying it concurrently
当可以同时修改和读取集合时,仅阻止并发修改是不够的.您需要防止与修改同时发生的读取,否则您将看到随机异常.
When a collection can be modified and read at the same time, it is not enough to prevent concurrent modification. You need to prevent reads that happen concurrently with modification, otherwise you would see random exceptions.
您可以通过制作 applicationNames
的副本来解决此问题:
You can work around this by making a copy of applicationNames
:
private static IList<ApplicationNames> ApplicationNamesSync {
get {
// Use the same synchronization that prevents concurrent modifications
lock (appNamesLock) {
return applicationNames.ToList(); // Make a copy
}
}
}
现在您的代码可以使用了:
Now your code will work:
List<ApplicationNames> originalApplicationNames = new List<ApplicationNames>(copyOfCachedVersions.Keys.ToList());
var exceptNames = ApplicationNamesSync.Except( originalApplicationNames );
if (exceptNames != null && exceptNames.ElementAtOrDefault(0) != default(ApplicationNames)) {
...
}
这篇关于Linq.Enumerable的界外索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!