ASP.NET应用程序从Session.Remove实现中抛出System.NullReferenceException

时间:2013-01-10 01:11:10

标签: asp.net session nullreferenceexception

我们在ASP.NET Web应用程序中得到随机的System.NullReferenceException。 我们正在使用inproc会话状态。 堆栈跟踪:

System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Specialized.NameObjectCollectionBase.BaseRemove(String name)
at System.Web.SessionState.SessionStateItemCollection.Remove(String name)
at System.Web.SessionState.HttpSessionStateContainer.Remove(String name)
at System.Web.UI.SessionPageStatePersister.Save()
at System.Web.UI.Page.SaveAllState()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

问题似乎来自Page.PageStatePersister属性,我们已经覆盖了这个。

protected override PageStatePersister PageStatePersister {
  get {
    return new SessionPageStatePersister(Page); 
  }
}

Reflector显示SessionPageStatePersister在内部调用Session.Remove。

我们在Page上直接调用Session.Remove时会得到类似的随机NullReferenceException。 相关的堆栈跟踪:

---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Specialized.NameObjectCollectionBase.BaseRemove(String name)
at System.Web.SessionState.SessionStateItemCollection.Remove(String name)
at System.Web.SessionState.HttpSessionStateContainer.Remove(String name)
at System.Web.SessionState.HttpSessionState.Remove(String name)
at PERH.WebFramework.Bases.PageBase.OnPreInit(EventArgs e) in 

任何想法,可能导致这些例外的原因是什么?

环境:

IIS6,Windows Server 2003 64位,.net Framework 3.5

1 个答案:

答案 0 :(得分:1)

同时处理同一用户(来自同一会话ID)发出的请求时,可能会出现此问题。

这是因为System.Web.SessionState.SessionStateItemCollection在删除条目时不会检查该条目是否为空。

System.Web.SessionState.SessionStateItemCollection.Remove(string name)方法中,在私有集合 _serializedItems 上设置了锁,以便删除操作是线程安全的。然而,在添加操作期间,此私人收藏并未锁定。考虑到 _serializedItems 表现为一个调整大小的数组(当条目数量>> =其容量的1/2时,容量加倍,新条目填充空值)并发添加可能会导致null值保留在集合中间的情况。 这些条目仅从[0;条目计数] _serializedItems集合的范围。删除条目时,访问其Key属性而不进行空检查。因此,如果 null 条目从集合中间删除,NullReferenceException将被强制转换。

默认情况下,除非System.Web.Configuration.PagesSection.EnableSessionState显式设置为ReadOnly,否则将按顺序处理具有相同会话ID的所有请求。 在这种情况下,任何涉及将值添加到System.Web.SessionState.HttpSessionState(内部使用System.Web.SessionState.HttpSessionStateContainer而内部使用System.Web.SessionState.SessionStateItemCollection)的操作都应正确锁定以确保线程安全。