0

我在 Global.asax.cs 文件(ASP.NET、C#、.NET Framework 4)的 Session_Start 方法中经常出现错误。错误似乎发生在以下行

if (!OnlineVisitorsUtility.Visitors.ContainsKey(currentContext.Session.SessionID))

它基本上检查这个 sessionId 是否在当前的 SessionIds 列表中。

错误是

System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at TestSystem.WebSite.Global.Session_Start(Object sender, EventArgs e) Global.asax.cs:line 142
at System.Web.SessionState.SessionStateModule.CompleteAcquireState()
at System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source, EventArgs e, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

没有用户针对该错误登录(因为这是在任何人登录之前引发的)。但是没有用户报告尝试登录的错误,我们看到这个的唯一原因是因为它出现在错误日志中。

该错误每分钟左右发生几天,然后停止几天,然后重新浮出水面。我们记录每个错误的远程主机 ip,对于我查看的每个错误实例,它都是不同的。我最初认为这是某种自动化的工作,但是当我跟踪位置 IP 地址时,我发现它源自我们有用户的地方,我们没有的地方和一个私人(我猜是内部)IP 地址.

我们无法在我们的内部测试和 QA 系统上复制此错误。我在两个方面寻求帮助,首先,任何人都知道可能导致此问题的原因,其次,如果没有,我可以记录哪些信息来阐明导致此问题的原因?

谢谢,尼尔

编辑

上面错误跟踪中的字典是一个存储 SessionId 和 WebsiteVisitor 类的字典。

public static Dictionary<string, WebsiteVisitor> Visitors = new Dictionary<string, WebsiteVisitor>();

我们仅在检查了上面的 ContainsKey if 语句后才添加此内容。整个声明如下

lock (visitorsLock)
{
    if (!OnlineVisitorsUtility.Visitors.ContainsKey(currentContext.Session.SessionID))
    {
        OnlineVisitorsUtility.Visitors.Add(currentContext.Session.SessionID, new WebsiteVisitor(currentContext));
    }
}
4

1 回答 1

1

听起来你的Visitors字典有同步问题。Dictionary集合不是线程安全的,因此需要控制读/写访问。我看到您使用锁定对象来解决此问题,但是,这种方法的问题是 IIS 不能保证每个请求都将在同一个 AppDomain 实例甚至同一个工作进程下运行。

而不是跨线程锁定,您需要查看跨进程锁定,我建议使用Mutex

更新

实际上@RichardDeeming 提出了一个很好的观点 - 访客对象不会在多个进程/AppDomain 之间共享,因此在这方面它不会是同步问题,但是,字典正在以某种方式损坏。我建议切换到使用ConcurrentDictionary并让框架为您处理同步。

通常,Web 应用程序中的静态属性不是一个好主意,因为它们不能在多个 AppDomain 之间共享,您最终可能会遇到这样的神秘问题。

于 2012-11-23T13:45:01.950 回答