Angular调用C# PowerBI API时请求持续Pending状态求助
解决Angular调用C# API请求Pending的问题
嘿,我看到你遇到了API请求一直Pending的问题,十有八九是C#代码里的异步处理不当导致的死锁,咱们一起来捋一捋~
核心问题:同步阻塞异步操作引发死锁
你的getToken方法里用了token.Result来同步获取AcquireTokenAsync的结果,这在ASP.NET环境下非常容易触发死锁:
AcquireTokenAsync是异步方法,执行时会释放当前线程- 调用
.Result会阻塞当前线程,等待异步操作完成 - 异步操作结束后需要回到原ASP.NET上下文,但这个上下文已经被阻塞的线程占用,形成死锁,导致API一直挂起无法返回
修复方案:全链路异步化
我们需要把所有涉及异步操作的方法改成异步模式,全程用await替代同步阻塞调用:
修改后的C# API代码
private static readonly string Tenant = "https://login.microsoftonline.com/{azure.tenant}/"; private static readonly string Resource = "https://analysis.windows.net/powerbi/api"; // 改为异步方法,返回Task<string> private async Task<string> getToken() { var authContext = new AuthenticationContext(Tenant); var clientCredential = new ClientCredential(AppId, AppSecret); var token = await authContext.AcquireTokenAsync(Resource, clientCredential); return token.AccessToken; } // 同理改为异步方法,返回Task<PowerBIClient> private async Task<PowerBIClient> getPBIClient() { var token = new TokenCredentials(await getToken(), "Bearer"); return new PowerBIClient(new Uri("https://api.powerbi.com/"), token); } public async Task<ODataResponseListReport> getReportsAsync(string ws) { // 异步获取PowerBIClient实例 PowerBIClient pbiClient = await getPBIClient(); var reports = await pbiClient.Reports.GetReportsInGroupAsync(ws); return reports; } public async Task<ReportEmbeddingData> getReportEmbeddingDataAsync(string ws, string rep) { PowerBIClient pbiClient = await getPBIClient(); var report = await pbiClient.Reports.GetReportInGroupAsync(ws, rep); var embedUrl = report.EmbedUrl; var reportName = report.Name; GenerateTokenRequest genTokenReqParam = new GenerateTokenRequest(accessLevel: "view"); string embedToken = (await pbiClient.Reports.GenerateTokenInGroupAsync(ws, rep, genTokenReqParam)).Token; return new ReportEmbeddingData { reportId = rep, reportName = reportName, embedUrl = embedUrl, accessToken = embedToken }; }
额外注意:控制器方法也要保持异步
确保你的API控制器调用上述方法时也是异步的,比如:
[HttpGet] public async Task<IActionResult> Get(string ws) { var result = await getReportsAsync(ws); return Ok(result); }
Angular代码小优化
虽然你说TS代码没问题,但可以用ES6模板字符串让参数拼接更清晰易读:
getReports(){ this.http.get(`http://localhost:44391/api/Auth?ws=${this.workspaceId}`) .subscribe((response) => { this.reportArray = response; console.log(this.reportArray); }); }
这样修改后,异步操作会正确释放上下文,避免死锁,你的API请求应该就能正常返回结果啦~
内容的提问来源于stack exchange,提问作者Luís Basto
相关产品推荐
相关产品推荐

