ASP.NET Core中ServiceBusSender.SendMessageAsync出错未抛异常排查
问题原因与修复方案
核心问题:异步方法未正确等待(await)
你的代码中最关键的错误是在AccountService.VerifyRedemption中调用异步方法ServiceBusService.SendMessage时没有使用await,导致异步操作的异常无法被上层的try/catch捕获:
SendMessage是返回Task的异步方法,直接调用SendMessage(redemptionRequest)而不await,会让这个异步任务在后台执行,当前线程继续往下执行更新数据库等逻辑,完全不等待消息发送的结果。- 当队列禁用或网络中断时,
SendMessageAsync确实会抛出异常,但这个异常属于未观察到的任务异常,不会传递到AccountController的try/catch块中,只会被全局异常捕获机制(比如App Insights)记录,而API会直接返回成功响应,导致你误以为没有抛出异常。
修复步骤
修改AccountService的方法为异步:
将VerifyRedemption改为async Task方法,并等待SendMessage完成:public async Task VerifyRedemption ( string username, RedemptionVerificationRequest request, string apiConsumerName ) { // 原有验证逻辑... if (AppSettings.ServiceBusRepayReinvest.ServiceBusEnabled) { // 必须添加await等待异步操作完成 await ServiceBusService.SendMessage(redemptionRequest); } // 原有数据库更新逻辑... }修改AccountController的方法为异步:
对应上层的Controller方法也要改为异步,等待Service方法完成:public async Task<ActionResult<SuccessOkResponse>> VerifyRedemption ( [FromQuery, Required] string username, [FromBody, Required] RedemptionVerificationRequest request ) { try { await Service.VerifyRedemption(username, request, HttpContext.User.Identity?.Name); return Ok(new SuccessOkResponse { Success = true }); } catch (Exception exc) { // 原有异常处理逻辑,现在可以捕获到SendMessage抛出的异常 ProblemDetails problemDetails; var exceptionType = exc.GetType(); // ... } }
额外优化建议
- 复用ServiceBusClient实例:你的代码中每次调用
SendMessage都创建新的ServiceBusClient实例,这不符合Azure Service Bus SDK的最佳实践。ServiceBusClient是线程安全的,应该单例注入复用,频繁创建销毁会导致连接资源浪费和性能问题。 - 添加超时与重试配置:可以在
ServiceBusClientOptions中配置重试策略(比如RetryOptions),应对临时的网络波动或服务端错误;也可以通过CancellationToken给SendMessageAsync设置超时,避免长时间等待。
内容的提问来源于stack exchange,提问作者some_randomer
相关产品推荐
相关产品推荐

