Reputation: 863
I've been getting this error intermittently in a service I'm working on
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)
The code looks like this:
List<ApplicationNames> originalApplicationNames = new List<ApplicationNames>(copyOfCachedVersions.Keys.ToList());
var exceptNames = applicationNames.Except( originalApplicationNames );
if (exceptNames != null && exceptNames.ElementAtOrDefault(0) != default(ApplicationNames))
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();
With the same results
I'm really stuck at this point, so any help would be greatly appreciated!
Upvotes: 2
Views: 3798
Reputation: 726479
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.
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)) {
...
}
Upvotes: 5