C# 索引超出边界异常

C# 索引超出边界异常,c#,exception,dictionary,static,C#,Exception,Dictionary,Static,我有以下代码,昨天晚上它抛出了很多异常: 引发了类型为“System.Web.HttpUnhandledException”的异常。-->System.IndexOutOfRangeException:索引超出了数组的边界。 at System.Collections.Generic.Dictionary`2.Insert(TKey键、TValue值、布尔加法) 我只是不明白这是怎么可能的,我会检查null以及密钥是否可用。这是使用lastTimeoutCheck的唯一方法 private st

我有以下代码,昨天晚上它抛出了很多异常:

引发了类型为“System.Web.HttpUnhandledException”的异常。-->System.IndexOutOfRangeException:索引超出了数组的边界。 at System.Collections.Generic.Dictionary`2.Insert(TKey键、TValue值、布尔加法)

我只是不明白这是怎么可能的,我会检查null以及密钥是否可用。这是使用lastTimeoutCheck的唯一方法

private static Dictionary<string, DateTime> lastTimeoutCheck;
private static readonly object CacheLock = new object();
private static void CheckTimeout(string groupName)
{
    if (lastTimeoutCheck == null)
    {
        lastTimeoutCheck = new Dictionary<string, DateTime>();
        return;
    }
    if (!lastTimeoutCheck.ContainsKey(groupName))
    {
        lastTimeoutCheck.Add(groupName, DateTime.UtcNow);
        return;
    }

    if (lastTimeoutCheck[groupName] <
        DateTime.UtcNow.AddMinutes(-GroupConfigSection.TimeOutCheckMinutes))
    {
        lock (CheckLock)
        {
            if (lastTimeoutCheck[groupName] <
                DateTime.UtcNow.AddMinutes(-GroupConfigSection.TimeOutCheckMinutes))
            {
                GroupHolder groupHolder =
                    (GroupHolder) System.Web.HttpContext.Current.Cache.Get(groupName);
                if (groupHolder != null)
                {
                    groupHolder.UpdateTime();
                }

                lastTimeoutCheck[groupName] = DateTime.UtcNow;
            }
        }
    }
}
私有静态字典lastTimeoutCheck;
私有静态只读对象CacheLock=新对象();
私有静态无效检查超时(字符串groupName)
{
如果(lastTimeoutCheck==null)
{
lastTimeoutCheck=新字典();
返回;
}
如果(!lastTimeoutCheck.ContainsKey(groupName))
{
添加(groupName,DateTime.UtcNow);
返回;
}
如果(lastTimeoutCheck[groupName]<
DateTime.UtcNow.AddMinutes(-GroupConfigSection.TimeOutCheckMinutes))
{
锁(检查锁)
{
如果(lastTimeoutCheck[groupName]<
DateTime.UtcNow.AddMinutes(-GroupConfigSection.TimeOutCheckMinutes))
{
股东股东=
(GroupHolder)System.Web.HttpContext.Current.Cache.Get(groupName);
if(groupHolder!=null)
{
groupHolder.UpdateTime();
}
lastTimeoutCheck[groupName]=DateTime.UtcNow;
}
}
}
}

由于您的变量是
静态的
,并且错误指示它在web服务器上运行,因此您很可能面临两个线程同时访问相同值的问题,从而导致同时进行两次加法运算

解决方案取决于您的情况:

  • 如果不希望在会话间共享词典,请不要将其设置为静态。这并不能真正解决问题。这使得它更不可能发生
  • 使用线程安全字典类型:

  • 您是否从多个线程使用此方法
    Dictionary
    不是线程安全的。如果查看错误消息,您将看到错误发生在
    Dictionary.Insert()
    。你确定
    groupName
    有一个有效值吗?@JonSkeet我不使用任何线程。@BvdVen那么为什么要锁定
    CheckLock
    在其他用户运行代码时执行代码,所以你有多个线程!锁不会注意字典不会同时更改吗?@BvdVen:不会,因为并非所有访问都在锁内执行。@BvdVen是的,如果您锁定整个方法的内容,但有效地使用锁需要深入了解和谨慎。你不能在任何你担心并发访问的地方设置一个锁。这可能会造成死锁、性能下降等。此语句可能仍会导致问题,因为它不在
    锁中
    lastTimeoutCheck.Add
    。这可能会导致字典调整大小,并且在此过程中可能会丢失数据。