You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

可能原因与解决方案建议

  1. 服务生命周期不匹配

    • 问题点:WirelessDevicesNewService注册为Scoped,但在MVC环境中,Blazor自定义元素的生命周期和独立Blazor应用存在差异——独立Blazor中Scoped服务跟随组件生命周期,而MVC中可能因宿主页面的DOM操作(比如动态加载/卸载元素)导致服务提前被释放。
    • 解决方案:尝试将WirelessDevicesNewService的注册改为Transient,确保每次使用时创建新实例,避免因实例被提前释放导致HttpClient失效:
      // 替换原Scoped注册
      _builder.Services.AddTransient<WirelessDevicesNewService>();
      
  2. 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>();
      
  3. Blazor宿主初始化时机问题

    • 问题点:在MVC页面中,Blazor自定义元素的初始化可能早于WebAssemblyHost完全启动,导致HttpClientFactory创建的HttpClient实例未完成初始化就被调用,后续触发释放异常。
    • 解决方案:在MVC页面中确保Blazor初始化完成后再调用组件的方法。可以通过监听Blazor的webassemblyready事件:
      <!-- 在MVC页面的脚本中添加 -->
      <script>
          window.addEventListener('webassemblyready', () => {
              // 此时再初始化或调用自定义元素的方法
              const element = document.querySelector('x-wireless-devices');
              // 执行相关操作
          });
      </script>
      
  4. HttpClientHandler生命周期问题

    • 问题点:WirelessDeviceNewFakeHttpMessageHandler注册为Transient,但HttpClient的Handler可能被复用或提前释放。
    • 解决方案:尝试将Handler改为Scoped注册,或检查Handler内部是否有未正确处理的资源释放逻辑:
      _builder.Services.AddScoped<WirelessDeviceNewFakeHttpMessageHandler>();
      

内容的提问来源于stack exchange,提问作者snowfrogdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 15:26:01