在ASP.NET MVC集成Blazor自定义元素时出现ThreadPool回调异常
问题:Blazor自定义元素集成到ASP.NET MVC时触发ObjectDisposedException异常
- 开发流程:先在独立Blazor WebAssembly应用中开发组件(利用热模块重载),发布后将编译文件迁移至遗留ASP.NET MVC应用中使用。
- 异常现象:仅在ASP.NET MVC环境中使用编译后的自定义元素时,抛出以下异常,独立Blazor应用中无此问题:
ThreadPool Callback threw an unhandled exception of type System.ObjectDisposedException
相关代码
服务类代码(WirelessDevicesNewService.cs)
// ... [Namespace imports] public class WirelessDevicesNewService { private readonly HttpClient _HttpClient; public WirelessDevicesNewService(IHttpClientFactory _p_HttpClientFactory) { _HttpClient = _p_HttpClientFactory.CreateClient(nameof(WirelessDevicesNewService)); } public async Task<IEnumerable<DeliveryCenterModel>> GetDeliveryCenters() { Console.WriteLine(_HttpClient); // <- 此日志正常输出 var _dto = await _HttpClient.GetFromJsonAsync<IEnumerable<DeliveryCenterDto>>("xApi/DeliveryCenters"); Console.WriteLine(_dto); // <- 异常在此行执行前抛出 //... [剩余逻辑] } //... }
Program.cs配置代码
// ... [Namespace imports] Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Mylicence"); var _builder = WebAssemblyHostBuilder.CreateDefault(args); //... [其他配置] _builder.Services.AddTransient<WirelessDeviceNewFakeHttpMessageHandler>(); _builder.Services.AddHttpClient<WirelessDevicesNewService>(_p_Client => { _p_Client.BaseAddress = new Uri(_builder.HostEnvironment.BaseAddress); }) .ConfigurePrimaryHttpMessageHandler<WirelessDeviceNewFakeHttpMessageHandler>(); _builder.Services.AddScoped<WirelessDevicesNewService>(); _builder.RootComponents.RegisterCustomElement<WirelessDevicesNew>("x-wireless-devices"); //... [其他服务注册] await _builder.Build().RunAsync();
注:已通过日志确认异常并非来自自定义HttpMessageHandler
可能原因与解决方案建议
服务生命周期不匹配
- 问题点:
WirelessDevicesNewService注册为Scoped,但在MVC环境中,Blazor自定义元素的生命周期和独立Blazor应用存在差异——独立Blazor中Scoped服务跟随组件生命周期,而MVC中可能因宿主页面的DOM操作(比如动态加载/卸载元素)导致服务提前被释放。 - 解决方案:尝试将
WirelessDevicesNewService的注册改为Transient,确保每次使用时创建新实例,避免因实例被提前释放导致HttpClient失效:// 替换原Scoped注册 _builder.Services.AddTransient<WirelessDevicesNewService>();
- 问题点:
BaseAddress配置差异
- 问题点:独立Blazor应用中
_builder.HostEnvironment.BaseAddress指向Blazor应用根目录,而MVC环境中该地址可能指向MVC站点根目录,导致HttpClient请求的URL不正确,间接引发资源释放异常。 - 解决方案:显式指定API的完整BaseAddress,而非依赖
HostEnvironment.BaseAddress:_builder.Services.AddHttpClient<WirelessDevicesNewService>(_p_Client => { // 替换为实际API的基础地址,比如MVC站点的API根路径 _p_Client.BaseAddress = new Uri("https://your-mvc-site.com/api/"); }) .ConfigurePrimaryHttpMessageHandler<WirelessDeviceNewFakeHttpMessageHandler>();
- 问题点:独立Blazor应用中
Blazor宿主初始化时机问题
- 问题点:在MVC页面中,Blazor自定义元素的初始化可能早于WebAssemblyHost完全启动,导致HttpClientFactory创建的HttpClient实例未完成初始化就被调用,后续触发释放异常。
- 解决方案:在MVC页面中确保Blazor初始化完成后再调用组件的方法。可以通过监听Blazor的
webassemblyready事件:<!-- 在MVC页面的脚本中添加 --> <script> window.addEventListener('webassemblyready', () => { // 此时再初始化或调用自定义元素的方法 const element = document.querySelector('x-wireless-devices'); // 执行相关操作 }); </script>
HttpClientHandler生命周期问题
- 问题点:
WirelessDeviceNewFakeHttpMessageHandler注册为Transient,但HttpClient的Handler可能被复用或提前释放。 - 解决方案:尝试将Handler改为Scoped注册,或检查Handler内部是否有未正确处理的资源释放逻辑:
_builder.Services.AddScoped<WirelessDeviceNewFakeHttpMessageHandler>();
- 问题点:
内容的提问来源于stack exchange,提问作者snowfrogdev
相关产品推荐
相关产品推荐

