【问题标题】:Index outside of bound exception超出绑定异常的索引
【发布时间】:2014-11-21 03:32:57
【问题描述】:

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

引发了“System.Web.HttpUnhandledException”类型的异常。 ---> System.IndexOutOfRangeException:索引超出了数组的范围。 at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)

我只是不明白这是怎么可能的,我检查 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;
            }
        }
    }
}

【问题讨论】:

  • 你是在多线程中使用这个方法吗? Dictionary&lt;,&gt; 不是线程安全的。
  • 如果您查看错误消息,您会看到错误发生在Dictionary&lt;Tkey, Tvalue&gt;.Insert()。您确定groupName 的值有效吗?
  • @JonSkeet 我不使用任何线程。
  • @BvdVen 那么为什么要锁定CheckLock
  • the code executed while an other user is already running the code 所以你有多个线程!

标签: c# exception dictionary static


【解决方案1】:

由于您的变量是static,并且错误表明它在Web 服务器上运行,因此您很可能面临两个线程同时访问相同值的问题,从而导致同时进行两个相加。

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

  1. 如果您不打算跨会话共享字典,请不要创建字典static。这并不能真正解决问题。它使它更不可能发生;
  2. 使用线程安全字典类型:ConcurrentDictionary

【讨论】:

  • 锁不会同时注意字典不改吗?
  • @BvdVen:不,因为并非所有访问都在锁内执行。
  • @BvdVen 是的,如果您锁定整个方法的内容,但有效地使用锁定需要洞察力和谨慎。您不能只在担心并发访问的任何地方加锁。这可能会造成死锁、性能下降等等。
  • 此语句可能仍会导致问题,因为它不在 lock:lastTimeoutCheck.Add 内。它可能会导致字典调整大小,并且您可能会在此过程中丢失数据。
猜你喜欢
  • 1970-01-01
  • 2017-09-10
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多