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

.NET 8 Blazor Server在Firefox中关闭页面后Dispose延迟3分钟触发求助

问题描述

我正在使用.NET 8 Blazor Server,开发了一个实现IDisposable接口的Razor组件。该组件的Dispose方法用于停止并释放控制单例服务的计时器。在Firefox浏览器中关闭页面后,Dispose方法需要等待约3分钟才会被调用;而在Google Chrome和Edge浏览器中,Dispose会按预期立即触发。

组件代码片段:

@implements IDisposable

...

// Dispose is taking 3 minutes to call after the page is closed
public void Dispose()
{
    scannerService.Close();
    excitationProbeService.Close();

    connectivityTimer.Stop();
    connectivityTimer.Dispose();

    excitationProbeLoadTimer.Stop();
    excitationProbeLoadTimer.Dispose();

    _logger.LogInformation("Scan Stopped. Disposed of all resources.");
}

请问是否有可行的解决方法?或者其他检测用户离开页面的方式?


解决方法

1. 用JavaScript监听页面卸载事件主动通知组件

Blazor Server的IDisposable触发依赖SignalR连接断开,Firefox在页面关闭时可能不会立即切断长连接,导致Dispose延迟。可以通过JS监听页面卸载事件,主动调用组件的资源清理方法:

  • 组件中添加可被JS调用的方法:
[JSInvokable]
public void CleanupResources()
{
    scannerService.Close();
    excitationProbeService.Close();

    connectivityTimer.Stop();
    connectivityTimer.Dispose();

    excitationProbeLoadTimer.Stop();
    excitationProbeLoadTimer.Dispose();

    _logger.LogInformation("Scan Stopped. Resources cleaned up via JS event.");
}
  • 在组件的OnAfterRenderAsync中注册卸载事件:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await JS.InvokeVoidAsync("registerUnloadHandler", DotNetObjectReference.Create(this));
    }
}
  • 在wwwroot的JS文件(如site.js)中添加事件处理逻辑:
window.registerUnloadHandler = (componentRef) => {
    window.addEventListener('beforeunload', () => {
        componentRef.invokeMethodAsync('CleanupResources');
        // 手动断开SignalR连接,加速组件释放
        window.Blazor.defaultConnection.stop();
    });
};

2. 调整SignalR的断开超时配置

在Program.cs中修改SignalR的超时参数,缩短Firefox下的等待时长:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        // 设置客户端断开后服务器的等待超时(示例设为30秒)
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
        // 缩短心跳包发送间隔,加快断开检测
        options.KeepAliveInterval = TimeSpan.FromSeconds(10);
    });

3. 优化单例服务的资源管理逻辑

单例服务会被多个组件共享,直接在组件Dispose中操作单例服务存在风险,建议调整为:

  • 让单例服务自行管理计时器生命周期,组件仅负责订阅/取消服务事件
  • 组件维护独立的计时器实例,而非直接操作单例服务的计时器

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:25:06