当会话处于活动状态时,我无法在asp.net中一次发出多个请求。为什么存在这种限制?有办法解决它吗?
这个问题可以通过一个只有3个简单aspx页面的WebForms应用程序来演示(虽然这个限制仍然适用于asp.net mvc)。
创建一个asp.net 3.5 Web应用程序。
应该只有三页: NoWait.aspx,Wait.aspx和SessionStart.aspx
NoWait.aspx在默认div标签之间添加了这个单个块:<%= DateTime.Now.Ticks%>。此页面的代码隐藏是默认值(空)。
Wait.aspx看起来就像NoWait.aspx,但在代码隐藏中有一行添加到Page_Load:Thread.Sleep(3000); //等3秒
SessionStart.aspx看起来也像NoWait.aspx,但它在代码隐藏中有这一行:Session [“Whatever”] =“Anything”;
打开浏览器并转到NoWait.aspx。它在响应中正确显示了一个数字,例如:“633937963004391610”。保持清爽,并不断改变数量。到目前为止很棒!在同一浏览器中创建一个新选项卡,然后转到Wait.aspx。它坐3秒钟,然后将数字写入响应。到目前为止很棒!不,试试这个:转到Wait.aspx,当它旋转时,快速切换到NoWait.aspx并刷新。即使在Wait.aspx正在睡眠时,NoWait.aspx也会提供响应。到目前为止很棒。在Wait.aspx旋转时,您可以继续刷新NoWait.aspx,服务器每次都会愉快地发送响应。这是我期望的行为。
现在它变得奇怪了。
在第3个标签中,在同一浏览器中,访问SessionStart.aspx。接下来,选中Wait.aspx并刷新。当它旋转时,切换到NoWait.aspx并刷新。在Wait.aspx完成运行之前,NoWait.aspx不会发送响应!
这证明,当会话处于活动状态时,您无法与同一用户进行并发请求。请求全部排队并同步提供。我不指望或理解这种行为。我在Visual Studio 2008的内置Web服务器以及IIS 7和IIS 7.5上进行了测试。
所以我有几个问题:
1)我是否认为这里确实存在限制,或者我的测试是否无效,因为我做错了什么?
2)有办法解决这个限制吗?在我的网络应用程序中,某些事情需要很长时间才能执行,我希望用户能够在等待大量请求完成时在其他选项卡中执行操作。我可以以某种方式配置会话以允许“脏读”吗?这可以防止它在请求期间被锁定?
3)为什么存在这种限制?我想很好地理解为什么这种限制是必要的。如果我知道的话,我想我会成为更好的开发者!
答案 0 :(得分:11)
Here is a link talking about session state and locking.它执行并独占锁定。
最简单的方法是使长时间运行的任务异步。您可以使长时间运行的任务在单独的线程上运行,或者使用asynchronous delegate并立即向浏览器返回响应。客户端页面可以向服务器发送请求以检查并查看它是否已完成(最有可能通过ajax),并且当服务器告知客户端它已完成时,通知用户。这样,虽然服务器请求必须一次一个地处理,但它对用户来说看起来不像。
这确实有它自己的一组问题,你必须确保关闭HTTP上下文的帐户,因为它将在asp.net会话中处理某些功能。您可能需要考虑的一个示例可能是释放对会话的锁定,如果实际发生的话。
这可能是一种限制并不令人惊讶。每个浏览器都有自己的会话,在ajax出现之前,回发请求是同步的。使相同的会话句柄并发可能会变得非常难看,我可以看到这不是IIS和ASP.NET团队加入的优先级。
答案 1 :(得分:9)
由于Kevin所描述的原因,用户无法访问可能同时写入其会话状态的两个页面 - 框架本身无法对会话存储的锁定进行细粒度控制,因此必须锁定整个请求。
要解决此问题,只有读取会话数据的页面才能声明他们这样做。 ASP.NET不会为它们获取会话状态写锁定:
// Or false if it doesn't need access to session state at all
EnableSessionState="ReadOnly"