Azure Service Bus连接串验证后添加单例客户端遇服务集合只读错误
问题描述
实现Azure Service Bus连接字符串验证后,尝试将Service Bus客户端以单例形式添加到服务集合时,抛出无效操作异常:The service collection cannot be modified because it is read-only。
验证及注册代码如下:
// 验证配置: await using var testClient = new ServiceBusClient(config.ServiceBusConnectionString); await using var testSender = testClient.CreateSender(config.QueueName); using var batch = await testSender.CreateMessageBatchAsync().ConfigureAwait(false); // 添加Azure Service Bus客户端: services.AddSingleton(provider => { var client = new ServiceBusClient( config.ServiceBusConnectionString, new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets }); return client; });
目标是确保配置的连接字符串和队列名称格式正确且能正常建立连接,需解决上述异常。
堆栈跟踪信息:
at Microsoft.Extensions.DependencyInjection.ServiceCollection.ThrowReadOnlyException() at Microsoft.Extensions.DependencyInjection.ServiceCollection.System.Collections.Generic.ICollection<Microsoft.Extensions.DependencyInjection.ServiceDescriptor>.Add(ServiceDescriptor item) at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(IServiceCollection services, Type serviceType, Func`2 implementationFactory) at Services.Audit.AuditServiceExtension.<AddAuditService>d__0.MoveNext() in C:\Users\Dumas.DED\Projects\Services.Audit\AuditServiceExtension.cs:line 36 at Services.Audit.AuditServiceExtension.<AddAuditService>d__0.MoveNext() in C:\Users\Dumas.DED\Projects\Services.Audit\AuditServiceExtension.cs:line 63 at Services.Audit.AuditServiceExtension.<AddAuditService>d__0.MoveNext() in C:\Users\Dumas.DED\Projects\Services.Audit\AuditServiceExtension.cs:line 63
解决方案
核心原因
该异常说明你试图在服务集合被标记为只读后修改它——通常是调用BuildServiceProvider()之后,或是在应用启动的后期阶段(比如中间件配置、请求处理阶段)尝试注册服务。
具体修复步骤
调整代码执行时机
将连接字符串验证和Service Bus客户端注册逻辑,移到应用启动的服务配置阶段(即Program.cs的builder.Services配置块,或自定义服务扩展方法中,且必须在BuildServiceProvider之前执行)。优化异步验证逻辑
验证操作是异步的,直接放在同步的服务配置阶段易导致阻塞,建议调整为:先注册客户端,再在应用启动完成后执行异步验证:// 先在服务配置阶段注册单例客户端 services.AddSingleton(provider => { var config = provider.GetRequiredService<IConfiguration>(); return new ServiceBusClient( config.GetValue<string>("ServiceBusConnectionString"), new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets }); }); // 应用启动后创建作用域执行异步验证 var app = builder.Build(); using var scope = app.Services.CreateScope(); var sbClient = scope.ServiceProvider.GetRequiredService<ServiceBusClient>(); var queueName = builder.Configuration.GetValue<string>("QueueName"); await using var testSender = sbClient.CreateSender(queueName); using var batch = await testSender.CreateMessageBatchAsync().ConfigureAwait(false);检查扩展方法调用时机
从堆栈跟踪可知异常出现在AuditServiceExtension.AddAuditService中,需确认该扩展方法是在BuildServiceProvider之前被调用的,不要在app.Use*等中间件配置步骤之后执行服务注册操作。
关键注意事项
- 服务集合在
BuildServiceProvider执行后会被设为只读,后续任何Add*操作都会触发该异常。 - 异步验证逻辑不要直接嵌套在同步的服务注册代码块中,避免死锁或异步操作未完成的问题。
内容的提问来源于stack exchange,提问作者Dumas.DED
相关产品推荐
相关产品推荐

