通过jQuery Ajax调用异步方法出现阻塞无响应问题
异步API调用阻塞问题的解决方案
以下是前端发起异步请求的jQuery代码:
function retrieveSummary() { $.ajax({ type: "POST", url: 'api/GetLeads', dataType: "json", async: true, error: function (xhr, textStatus, thrownError) { }, success: function (data) { }, failure: function (data) { } }); }
后端C#代码存在阻塞问题,注释已标注阻塞位置:
[HttpPost] [ActionName("GetLeads")] public List<Leads> GetSummary() { List<Leads> list = new List<Leads>(); var result = RunAsync(publicKey, secretKey).Result; var data = result.GetData(); // 处理数据并返回,但在下方异步方法RunAsync的await行处阻塞 . . } static async Task<Response> RunAsync(string publicKey, string secretKey) { Client client = new Client(publicKey, secretKey); Request request = new Request() { Resource = Message.Resource }; request.Filter(Message.Limit, limit) .Filter("FromTS", String.Format("{0:s}", fromDate)) .Filter("ToTS", String.Format("{0:s}", toDate)) .Filter("ShowContactAlt", "true") .Filter("ShowSubject", "true") .Filter("MessageStatus", 3) .Filter(Message.Offset, offSet); // Ajax请求在此处阻塞 return await client.GetAsync(request); }
问题根源
阻塞的核心原因是在同步方法中调用异步方法时使用了.Result。ASP.NET的请求上下文是单线程的,当你调用.Result时,当前线程会阻塞等待异步任务完成;而await client.GetAsync(request)执行完成后,需要回到原请求上下文继续处理,此时上下文已经被阻塞的线程占用,形成死锁。
修复方案
将控制器方法改为异步模式,全程使用await而非.Result:
[HttpPost] [ActionName("GetLeads")] // 改为异步方法,返回Task<List<Leads>> public async Task<List<Leads>> GetSummary() { List<Leads> list = new List<Leads>(); // 用await替代.Result var result = await RunAsync(publicKey, secretKey); var data = result.GetData(); // 处理数据并返回 . . } // 保持RunAsync的异步逻辑不变 static async Task<Response> RunAsync(string publicKey, string secretKey) { Client client = new Client(publicKey, secretKey); Request request = new Request() { Resource = Message.Resource }; request.Filter(Message.Limit, limit) .Filter("FromTS", String.Format("{0:s}", fromDate)) .Filter("ToTS", String.Format("{0:s}", toDate)) .Filter("ShowContactAlt", "true") .Filter("ShowSubject", "true") .Filter("MessageStatus", 3) .Filter(Message.Offset, offSet); return await client.GetAsync(request); }
关键说明
- 异步方法需遵循异步全链路原则:从控制器入口到底层异步调用,全程使用
async/await,避免同步阻塞异步任务 - 不要在ASP.NET环境中使用
.Result或.Wait()等待异步任务,这是死锁的常见诱因
内容的提问来源于stack exchange,提问作者Briskstar Technologies
相关产品推荐
相关产品推荐

