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

Blazor WebAssembly中如何通过JSRuntime结合CancellationToken终止页面销毁后的JavaScript长运行进程

解决Blazor WebAssembly页面销毁时终止JavaScript长进程的问题

你遇到的核心问题是:Blazor传递给InvokeAsync的CancellationToken只会取消.NET层面等待JS调用完成的任务,并不会主动终止JS端正在运行的代码。比如你用的setTimeout,一旦启动就会独立执行,和.NET的取消信号完全无关,所以页面销毁后它还是会按时触发。

下面是具体的解决方案,通过让JS代码支持主动取消,配合Blazor的页面销毁逻辑来彻底终止进程:

步骤1:修改JavaScript代码,支持取消机制

我们需要让JS函数返回可用于取消的标识(比如setTimeout的ID),并新增一个取消函数来终止进程:

(function () {
    window.testFunctions = {
        // 启动定时器并返回ID
        testFunction1: function (message, timeOutLength) {
            return setTimeout(function () {
                console.log(message);
            }, timeOutLength);
        },
        // 根据ID取消定时器
        cancelTimeout: function (timeoutId) {
            clearTimeout(timeoutId);
            console.log("已取消JavaScript定时器");
        }
    };
})();

步骤2:更新Razor页面代码,在Dispose时主动取消JS进程

我们需要保存JS返回的定时器ID,在页面销毁时调用JS的取消函数:

@page "/counter"
@inject IJSRuntime _jsRuntime
@implements IDisposable

@code {
    private CancellationTokenSource _jsCancellationToken = new();
    private int? _timeoutId; // 存储JS定时器的唯一ID

    protected override async Task OnInitializedAsync()
    {
        var message = "Hello!";
        var timeOutLength = 10000;
        
        // 调用JS函数并获取定时器ID
        _timeoutId = await _jsRuntime.InvokeAsync<int>(
            "testFunctions.testFunction1", 
            _jsCancellationToken.Token, 
            message, 
            timeOutLength);
    }

    public async void Dispose()
    {
        // 先取消.NET层面的等待任务
        _jsCancellationToken.Cancel();
        
        // 如果定时器已启动,调用JS函数取消它
        if (_timeoutId.HasValue)
        {
            try
            {
                await _jsRuntime.InvokeVoidAsync(
                    "testFunctions.cancelTimeout", 
                    _timeoutId.Value);
            }
            catch (Exception ex)
            {
                // 捕获可能的异常(比如JS上下文已失效)
                Console.WriteLine($"取消JS进程时出错: {ex.Message}");
            }
        }
        
        _jsCancellationToken.Dispose();
    }
}

关键知识点说明

  1. 为什么之前的方法无效?
    Blazor的CancellationToken仅作用于.NET端的异步等待逻辑——当你调用Cancel()时,只是让.NET不再等待JS调用的结果,但JS端的代码已经在浏览器的JS引擎中独立运行了,不会受到影响。

  2. 通用思路扩展
    如果你的JS长进程是更复杂的操作(比如fetch请求、Web Worker等),核心逻辑是一致的:

    • 在JS中创建可取消的控制器(比如AbortController)
    • 将控制器的取消句柄返回给.NET
    • 在页面Dispose时,调用JS的取消方法终止进程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:12:38