在通用列表中,List.Last()即使在检查Count之后也会抛出System.IndexOutOfRangeException

问题描述 投票:1回答:1

我在我的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

}

reqEndDatereqStartDate来自客户端计算机,按照日志,它们是正确的。 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)

我想知道,在什么时候可能发生这种异常

c# linq wcf indexoutofboundsexception generic-list
1个回答
1
投票

堆栈跟踪表明这是一个威胁问题。 Last()实现如下:

IList<TSource> sourceList = source as IList<TSource>;
if (sourceList != null)
{
    int count = sourceList.Count;
    if (count > 0)
      return sourceList[count - 1];
}

因此,如果IEnumerable传递实现IList(就像你的情况一样),它将首先在一个变量中保存总长度,然后将访问最后一个元素。如果source中的元素数量在sourceList.CountsourceList[count - 1]语句之间发生了变化,那么抛出堆栈跟踪异常的唯一方法是,这只能由另一个线程完成。

如果您使用共享缓存 - 可以由另一个WCF线程进行更改。所以要修复 - 在处理共享缓存中的项目时实现正确的同步。

© www.soinside.com 2019 - 2024. All rights reserved.