在通用列表中,List.Last() 即使在检查 Count 之后也会抛出 System.IndexOutOfRangeException
In generic list, List.Last() throws System.IndexOutOfRangeException even after check of Count
我的 WCF 服务中有以下代码,它抛出 System.IndexOutOfRangeException
Dictionary<string, List<ChunkData>> chunkDataTable = cacheManager[cacheKey] as Dictionary<string, List<ChunkData>>;
if (!chunkDataTable.Keys.Contains(ticker))
{
chunkDataTable.Add(ticker, new List<ChunkData>());
}
List<ChunkData> listOfChunks = new List<ChunkData>();
ChunkData lastIncompeleteChunk = null;
if (chunkDataTable[ticker].Count > 0)
{
Logger.Write("Log one"); //I see this logs
if (reqEndDate <= chunkDataTable[ticker].Last().EndDate)
{
//meaning we can directly take last chunk (which can be incompelete too) directly as we dont need to add further data into for now
listOfChunks = chunkDataTable[ticker].Where
(chunk =>
((chunk.StartDate >= reqStartDate && chunk.EndDate <= reqEndDate) || //whole chunks: which lies in between of requested start and end date
(chunk.StartDate <= reqStartDate && reqStartDate <= chunk.EndDate) || //Left Most Chunk: if req start date lies within some chunk (between start and end date of chunk)
(chunk.StartDate <= reqEndDate && reqEndDate <= chunk.EndDate) //Right Most Chunk: if req end date lies within some chunk (between start and end date of chunk)
)).OrderBy(x => x.EndDate).ToList();
}
else
{
listOfChunks = chunkDataTable[ticker].Where
(chunk => !chunk.IsIncomplete &&
((chunk.StartDate >= reqStartDate && chunk.EndDate <= reqEndDate) || //whole chunks: which lies in between of requested start and end date
(chunk.StartDate <= reqStartDate && reqStartDate <= chunk.EndDate) || //Left Most Chunk: if req start date lies within some chunk (between start and end date of chunk)
(chunk.StartDate <= reqEndDate && reqEndDate <= chunk.EndDate) //Right Most Chunk: if req end date lies within some chunk (between start and end date of chunk)
)).OrderBy(x => x.EndDate).ToList();
if (chunkDataTable[ticker].Last().IsIncomplete)
lastIncompeleteChunk = chunkDataTable[ticker].Last();
}
if (listOfChunks != null)
Logger.Write("Line two"); //I don't see this log
}
此处 reqEndDate
和 reqStartDate
来自客户端计算机,根据日志,它们是正确的。
cacheManager
是 Microsoft 企业库的缓存管理器
完整堆栈跟踪:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Linq.Enumerable.Last[TSource](IEnumerable`1 source)
我想知道,这种异常可能在什么时候发生
堆栈跟踪表明这是一个威胁问题。 Last()
是这样实现的:
IList<TSource> sourceList = source as IList<TSource>;
if (sourceList != null)
{
int count = sourceList.Count;
if (count > 0)
return sourceList[count - 1];
}
因此,如果 IEnumerable
您传递了 implements IList
(就像您的情况一样),它将首先将总长度保存在一个变量中,然后访问最后一个元素。如果 source
中的元素数量在 sourceList.Count
和 sourceList[count - 1]
语句之间发生更改,则可以抛出堆栈跟踪异常的唯一方法,这只能由另一个线程完成。
如果您正在使用共享缓存 - 可以由另一个 WCF 线程进行更改。因此,要修复 - 在处理共享缓存中的项目时实施正确的同步。
我的 WCF 服务中有以下代码,它抛出 System.IndexOutOfRangeException
Dictionary<string, List<ChunkData>> chunkDataTable = cacheManager[cacheKey] as Dictionary<string, List<ChunkData>>;
if (!chunkDataTable.Keys.Contains(ticker))
{
chunkDataTable.Add(ticker, new List<ChunkData>());
}
List<ChunkData> listOfChunks = new List<ChunkData>();
ChunkData lastIncompeleteChunk = null;
if (chunkDataTable[ticker].Count > 0)
{
Logger.Write("Log one"); //I see this logs
if (reqEndDate <= chunkDataTable[ticker].Last().EndDate)
{
//meaning we can directly take last chunk (which can be incompelete too) directly as we dont need to add further data into for now
listOfChunks = chunkDataTable[ticker].Where
(chunk =>
((chunk.StartDate >= reqStartDate && chunk.EndDate <= reqEndDate) || //whole chunks: which lies in between of requested start and end date
(chunk.StartDate <= reqStartDate && reqStartDate <= chunk.EndDate) || //Left Most Chunk: if req start date lies within some chunk (between start and end date of chunk)
(chunk.StartDate <= reqEndDate && reqEndDate <= chunk.EndDate) //Right Most Chunk: if req end date lies within some chunk (between start and end date of chunk)
)).OrderBy(x => x.EndDate).ToList();
}
else
{
listOfChunks = chunkDataTable[ticker].Where
(chunk => !chunk.IsIncomplete &&
((chunk.StartDate >= reqStartDate && chunk.EndDate <= reqEndDate) || //whole chunks: which lies in between of requested start and end date
(chunk.StartDate <= reqStartDate && reqStartDate <= chunk.EndDate) || //Left Most Chunk: if req start date lies within some chunk (between start and end date of chunk)
(chunk.StartDate <= reqEndDate && reqEndDate <= chunk.EndDate) //Right Most Chunk: if req end date lies within some chunk (between start and end date of chunk)
)).OrderBy(x => x.EndDate).ToList();
if (chunkDataTable[ticker].Last().IsIncomplete)
lastIncompeleteChunk = chunkDataTable[ticker].Last();
}
if (listOfChunks != null)
Logger.Write("Line two"); //I don't see this log
}
此处 reqEndDate
和 reqStartDate
来自客户端计算机,根据日志,它们是正确的。
cacheManager
是 Microsoft 企业库的缓存管理器
完整堆栈跟踪:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Linq.Enumerable.Last[TSource](IEnumerable`1 source)
我想知道,这种异常可能在什么时候发生
堆栈跟踪表明这是一个威胁问题。 Last()
是这样实现的:
IList<TSource> sourceList = source as IList<TSource>;
if (sourceList != null)
{
int count = sourceList.Count;
if (count > 0)
return sourceList[count - 1];
}
因此,如果 IEnumerable
您传递了 implements IList
(就像您的情况一样),它将首先将总长度保存在一个变量中,然后访问最后一个元素。如果 source
中的元素数量在 sourceList.Count
和 sourceList[count - 1]
语句之间发生更改,则可以抛出堆栈跟踪异常的唯一方法,这只能由另一个线程完成。
如果您正在使用共享缓存 - 可以由另一个 WCF 线程进行更改。因此,要修复 - 在处理共享缓存中的项目时实施正确的同步。