ASP Webform中如何让Ajax调用独立不阻塞后续服务端请求
你遇到的同用户请求排队问题,根本原因是ASP.NET Session的排他锁机制:只要接口开启了Session可写权限,来自同一个会话的所有请求默认会被串行执行,后发起的请求必须等待前一个同会话请求处理完成、释放Session锁之后才会开始执行,和前端Ajax调用本身无关,你当前的前端Ajax配置默认就是异步的,不需要做任何修改。
可落地解决方案
方案1:调整Session访问模式(改动最小,优先尝试)
如果你的接口仅需要读取Session、不需要写入,或者可以拆分读写逻辑,直接把WebMethod的Session权限改为只读即可解除排他锁:
将原方法的特性
[System.Web.Services.WebMethod(EnableSession = true)]
修改为:
[System.Web.Services.WebMethod(EnableSession = System.Web.Services.SessionStateBehavior.ReadOnly)]
注意:只读模式下Session仅支持读取操作,无法写入数据,如果你的业务必须要写入Session到会话中,该方案不适用,请参考方案2。
方案2:后台异步执行任务(适配必须写Session的场景)
不要在请求主线程中同步执行耗时的DB查询逻辑,把耗时任务丢到后台线程池执行,当前请求先立即返回响应给前端,后台任务执行完成后再写入Session即可:
[System.Web.Services.WebMethod(EnableSession = true)] [System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] public SomeReponseDto LoadData(SomeRequestDto requestDto) { // 提前取出需要的参数,避免后台线程丢失请求上下文 var dataType = requestDto.Type; var sessionId = Session.SessionID; // 把耗时任务丢到后台线程执行,不阻塞当前请求 _ = Task.Run(async () => { var neededData = await GetDataFromDB(); // 写入Session(如果后台拿不到当前HttpContext,可以通过SessionID用SessionStateUtility获取对应会话操作) if (HttpContext.Current != null) { // 补充:你原代码中的Session键拼接存在语法错误,此处已修正 HttpContext.Current.Session[$"{dataType}_Data"] = neededData; } }); // 直接返回任务已受理的响应,无需等待任务执行完成 return new SomeResponseDto { Status = true, Message = $"Data for {dataType} are processing." }; }
方案3:全局调整Session默认权限(可选)
如果全站大部分接口都不需要写入Session,可直接在Web.config中配置全局Session为只读模式,仅给需要写入Session的单独接口开可写权限即可:
<system.web> <pages enableSessionState="ReadOnly" /> <!-- 其余原有配置保持不变 --> </system.web>
内容的提问来源于stack exchange,提问作者nizoodxs
相关产品推荐
相关产品推荐

