我刚刚发现,ASP.Net Web应用程序中的每个请求在请求开始时都会获得一个Session锁,然后在请求结束时释放它!
如果这对你造成影响,就像我一开始对你而言,这基本上意味着以下几点:
任何时候ASP.Net网页需要很长时间才能加载(可能是由于数据库调用速度慢等),并且用户决定他们想要导航到另一个页面,因为他们厌倦了等待,他们不能!ASP.Net会话锁强制新页面请求等待,直到原始请求完成其缓慢的负载.Arrrgh.
任何时候UpdatePanel加载缓慢,并且用户决定在UpdatePanel完成更新之前导航到另一个页面......他们不能!ASP.net会话锁强制新页面请求等待原始请求完成其缓慢的负载.双Arrrgh!
那有什么选择呢?到目前为止,我想出了:
我真的不敢相信ASP.Net微软团队会在版本4.0的框架中留下如此巨大的性能瓶颈!我错过了一些明显的东西吗 为会话使用ThreadSafe集合有多难?
ASP.Net会话看起来非常适合传统的WebForms应用程序,但它们会为现代AJAX和MVC应用程序做一些严重问题.
具体来说,只有3种方法可以访问ASP.Net提供者:
锁定读写(默认) - 会话被锁定,AcquireRequestState直到ReleaseRequestState触发为止.如果浏览器立即发出3个请求,他们将在服务器上排队.这是MVC 2中唯一的选择,但MVC 3允许......
非锁定只读 - 会话未锁定,但无法保存.这似乎是不可靠的,因为有些读取似乎再次锁定会话.
会话已禁用 - 任何读取或写入会话的尝试都会引发异常.
然而,对于一个现代的MVC应用程序,我有很多AJAX事件同时发生 - 我不希望它们在服务器上的队列,但我希望他们能够写入会话.
我想要的是第四种模式:脏读,最后写赢
我认为(很高兴得到纠正)唯一的办法就是完全取代ASP.Net的会话.我可以编写自己的提供程序,但ASP仍会使用它支持的3个模式中的一个调用它.有没有办法让ASP.Net支持乐观并发?
这使得我用一个基本上做同样事情的新类替换对会话的所有调用,但是没有锁定 - 这是一个痛苦.
我希望保留尽可能多的当前会话内容(最重要的是在各种日志中的会话ID),并且代码更换量最少.有没有办法做到这一点?理想情况下,我想HttpContext.Current.Session指向我的新类,但没有ASP.Net锁定任何请求.
有没有人做过这样的事情?看来奇怪的是,所有的AJAXey MVC应用程序都是ASP的一个新问题.
ASP.NET不允许同一会话的并发请求; 意味着用户一次只能发出1个请求.
例如,假设我们有Test1.aspx:
public partial class Test1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Session["test"] = 1;
System.Threading.Thread.Sleep(int.Parse(Request.QueryString["timeout"]));
}
}
Run Code Online (Sandbox Code Playgroud)
......和Test2.aspx:
public partial class Test2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Session["test"] = 1;
Label1.Text = DateTime.Now.ToString("dd/MM/yy HH:mm:ss");
}
}
Run Code Online (Sandbox Code Playgroud)
当我们访问Test1.aspx?timeout=10000,然后在访问后立即Page2.aspx,第二个请求必须等待10秒,直到第一个请求完成.
我今天刚刚学会了这个,我已经使用ASP.NET 5年了!直到我在MSDN页面底部(ASP.NET会话状态概述)中读到它,我才真正相信它.
那么,有没有办法强制并发?也就是说,除了使页面更快,或将长时间运行的代码移动到后台线程之外.我知道你可以让会话只读,但我不完全确定这是一个实用的选择.
我有一个应用程序,它有一些控制器的动作调用缓慢的第三方Web服务.使用页面中的AJAX调用调用这些操作.
我可以使用异步控制器来释放ASP.NET线程池,这很棒.但会议呢?如果我使用InProc会话并且请求"慢动作",则特定用户不能向应用程序发出任何请求,因为他的会话被第一次"慢"调用锁定.
在PHP中有一个方法session_write_close(),我可以使用如下:
session_write_close().从这一点开始,会话将被此请求关闭,来自同一用户的任何其他请求都可以访问它我知道我可以使用[SessionState]属性在控制器级别禁用会话状态,但这不是解决方案.
有任何想法吗?