我想澄清一下ASP.NET会话的一些细节。我使用ASP.NET MVC 3.
假设我有一个标有[SessionState(SessionStateBehavior.ReadOnly)]
属性的控制器 - 所以它使用只读会话
会话处于InProc
模式
根据{{3}},对此控制器的请求获取读锁定,无法更新会话
如果他们试图更新会话值,我想了解这些请求(在一个公共会话中)是否仍然可以 ?
这些请求使用相同的会话数据结构,而不是单独的副本,对吧?
如何更新InProc
会话值?在请求结束时立即或OnReleaseState
事件发生?
OnReleaseState
处理程序中会发生什么?
更新
我正在调查以下异常:
System.ArgumentException: Item has already been added. Key in dictionary: 'MyKey' Key being added: 'MyKey'
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Specialized.NameObjectCollectionBase.BaseAdd(String name, Object value)
at System.Web.SessionState.SessionStateItemCollection.set_Item(String name, Object value)
只需访问会话的值(DateTime)context.Session["MyKey"]
即可。
MSDN描述了与ASP.NET会话非常相似的异常。
答案 0 :(得分:2)
只要您只在Session中存储不可变对象,就不存在竞争条件的风险。可以同时保持多个读锁定,但在保持写锁定时无法获取读锁定,并且在保持读锁定时无法获取写锁定。
如果在Session中存储可变的,非线程安全的对象,然后将Action标记为使用只读会话,则可能会遇到麻烦。
在这种情况下,您将被阻止(*)在Session中添加/替换对象。
(*)实际上你可以添加/替换它们,但它们不会在请求结束后持续存在。
但是你不会被阻止试图改变Session中对象的状态。
如果您的应用在Session中有可变对象,我建议您避免使用只读会话。
更新以回应评论
如果我尝试在读取器锁定下设置值
,该怎么办?
它只会持续请求的持续时间:您将处理InProc会话集合的浅表副本。
我正在调查System.ArgumentException:Item已经添加到System.Collections.Hashtable.Insert
堆栈跟踪说什么? 您是否插入了Session中已存在的Hashtable?在这种情况下,您可以获得如上所述的竞争条件。