.NET 6类库中Service Bus发送方法执行异常排查
问题描述
将Service Bus消息发送方法提取到.NET 6类库后,调用该方法时,程序执行CreateMessageBatchAsync后无异常退出,后续代码断点无法触发。原代码在控制台应用中可正常运行。
原控制台应用代码
var cln= new ServiceBusClient(connectionString); var sender = cln.CreateSender(topicName); var body = JsonSerializer.Serialize(obj); var message = new ServiceBusMessage(body) { ContentType = "application/json" }; try { var batch = await sender.CreateMessageBatchAsync(); var test = "123"; if (!batch.TryAddMessage(message)) { throw new Exception("Error occured while sending object to topic"); } await sender.SendMessagesAsync(batch); await sender.DisposeAsync(); await cln.DisposeAsync(); } catch (Exception ex) { Console.WriteLine($"Error sending message: {ex.Message}"); throw; }
迁移后的.NET 6类库方法代码
public async Task SendBatchMessageAsync(string connectionStr, string topic, ServiceBusMessage message, int maxRetries = 3) { int attempt = 0; do { try { var _client = new ServiceBusClient(connectionString); var _sender = _client.CreateSender(topic); var serviceBusMessageBatch = await _sender.CreateMessageBatchAsync(); if (!serviceBusMessageBatch.TryAddMessage(message)) { throw new Exception("Error occured"); } await _sender.SendMessagesAsync(serviceBusMessageBatch); await _sender.DisposeAsync(); await _client.DisposeAsync(); } catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.MessagingEntityDisabled || ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound || ex.Reason == ServiceBusFailureReason.ServiceTimeout || ex.Reason == ServiceBusFailureReason.ServiceBusy) { _logger.Error($"Transient exception caught: {ex.Message}"); attempt++; if (attempt >= maxRetries) throw; // Give up after maxRetries // Wait for a bit before retrying await Task.Delay(ComputeDelay(attempt)); } catch (Exception ex) { _logger.Error($"Error sending message: {ex.Message}"); throw; } } while (attempt < maxRetries); }
问题排查与修复
1. 参数名不匹配
类库方法接收的参数是connectionStr,但代码中使用的是未定义的connectionString,这会直接引发未初始化变量的异常。如果调用方未正确等待异步任务,异常会被吞掉,导致程序无提示退出。
修复:将方法内的connectionString替换为connectionStr,确保使用传入的连接字符串。
2. 异步方法未被正确等待
如果调用SendBatchMessageAsync时未添加await,或者在非异步上下文(比如控制台Main方法)中未正确处理异步任务,主线程会提前结束,看起来像是执行到CreateMessageBatchAsync后就退出了。
修复:调用方法时必须添加await;如果是控制台应用,将Main方法改为async Task Main,再用await调用发送方法。
3. 资源管理不合理
原类库代码每次重试都会创建新的ServiceBusClient和ServiceBusSender,频繁创建销毁会影响性能,且可能因异步释放问题引发隐藏异常。ServiceBusClient是线程安全的,建议作为单例复用。
优化后的示例代码:
// 通过依赖注入注入单例ServiceBusClient和Logger private readonly ServiceBusClient _client; private readonly ILogger _logger; public ServiceBusSenderService(ServiceBusClient client, ILogger logger) { _client = client; _logger = logger; } public async Task SendBatchMessageAsync(string topic, ServiceBusMessage message, int maxRetries = 3) { int attempt = 0; var sender = _client.CreateSender(topic); try { do { try { var batch = await sender.CreateMessageBatchAsync(); if (!batch.TryAddMessage(message)) { throw new Exception("消息过大无法加入批次"); } await sender.SendMessagesAsync(batch); return; } catch (ServiceBusException ex) when (ex.Reason is ServiceBusFailureReason.MessagingEntityDisabled or ServiceBusFailureReason.MessagingEntityNotFound or ServiceBusFailureReason.ServiceTimeout or ServiceBusFailureReason.ServiceBusy) { _logger.Error($"捕获到临时异常: {ex.Message}"); attempt++; if (attempt >= maxRetries) throw; await Task.Delay(ComputeDelay(attempt)); } catch (Exception ex) { _logger.Error($"发送消息出错: {ex.Message}"); throw; } } while (attempt < maxRetries); } finally { await sender.DisposeAsync(); } }
内容的提问来源于stack exchange,提问作者katie77
相关产品推荐
相关产品推荐

