ASP.NET MVC 5中Ajax异步HttpPost请求阻塞问题求助
嗨,我之前也踩过一模一样的坑!你遇到的问题根源就是ASP.NET的Session锁机制:默认情况下,同一个客户端(同一个SessionId)发起的所有请求都会被串行处理——因为Session对象本身不是线程安全的,ASP.NET为了避免并发读写冲突,会给每个Session的请求加独占锁。哪怕你设置了ReadOnly特性,依然会加上一个只读锁,后续请求还是得等着前面的锁释放。
你试过的ReadOnly之所以没解决问题,是因为只读锁依然会阻塞同一个Session的后续请求(尤其是写请求,甚至部分读请求也会被卡住)。给你几个靠谱的解决方案,按优先级排序:
1. 完全禁用控制器的Session(最彻底)
如果TestController里的这两个Action根本不需要访问Session,直接把Session状态设为Disabled,这样请求就不会触发任何Session锁,多个Ajax请求就能并行处理了:
[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)] public class TestController : SurfaceController { [HttpPost] public async Task<ActionResult> Test1() { // 用await Task.Delay代替Thread.Sleep,避免阻塞线程池线程 await Task.Delay(5000); return Json("1"); } [HttpPost] public async Task<ActionResult> Test2() { await Task.Delay(5000); return Json("2"); } }
2. 拆分无Session的Action到独立控制器
如果原TestController里还有其他需要Session的Action,别把它们混在一起——把Test1、Test2这类不需要Session的异步请求,单独放到一个禁用Session的控制器里,这样互不影响。
3. 改用异步Action配合无Session设置
你原来用的Thread.Sleep会直接阻塞线程池线程,就算解决了Session锁的问题,也会浪费服务器资源。换成await Task.Delay的异步写法,能让线程在等待期间去处理其他请求,提升整体性能。
4. 绕开Session存储共享数据(如果必须共享数据)
如果你的业务逻辑确实需要在请求间共享数据,但又不想被Session锁限制,可以改用其他线程安全的存储方式,比如:
- 分布式缓存(如Redis)
- 数据库存储
- 请求上下文(
HttpContext.Items,仅当前请求有效)
补充:为什么ReadOnly没生效?
SessionStateBehavior.ReadOnly只是告诉ASP.NET不要加独占写锁,但依然会加一个只读锁——这个锁会阻止同一个Session的后续写请求,而且在某些场景下(比如多个读请求同时发起),也可能导致排队。所以只有完全禁用Session,才能彻底消除这个排队问题。
内容的提问来源于stack exchange,提问作者Sharon

