Blazor 中 CancellationToken 用于安全取消异步操作,防止内存泄漏和 ui 异常;需在 OnInitializedAsync 中使用自动注入的 token,或手动管理 CancellationTokenSource 并在 Dispose 中取消释放。

Blazor 中的 CancellationToken 主要用于安全取消异步操作,避免组件已销毁或状态已变更时仍在执行无意义的耗时任务(比如 http 请求、定时器、长循环等),防止内存泄漏、UI 异常或陈旧数据覆盖。
在 OnInitializedAsync 中使用 CancellationToken
组件初始化时发起异步加载是最常见场景。Blazor 会自动将当前生命周期的取消令牌传入 OnInitializedAsync,你只需接收并传递给 awaitable 方法即可:
protected override async Task OnInitializedAsync() { try { // dataService.GetDataAsync 自动支持 CancellationToken items = await dataService.GetDataAsync(cancellationToken); } catch (OperationCanceledException) { // 被取消时静默处理(通常无需报错) } }
注意:必须确保底层方法(如 HttpClient.GetAsync 或自定义服务)真正接收并响应该 token,否则取消无效。
手动管理 CancellationTokenSource(适用于动态触发)
当操作由用户交互(如搜索框输入、按钮点击)触发,且需支持“取消前一个请求、发起新请求”时,应手动创建 CancellationTokenSource 并及时释放:
- 在组件字段中声明:
private CancellationTokenSource? _cts; - 每次触发新操作前,先调用
_cts?.Cancel(); _cts?.Dispose();,再新建_cts = new(); - 将
_cts.Token传给异步方法 - 在
Dispose方法中调用_cts?.Cancel(); _cts?.Dispose();防止残留
示例(搜索建议):
private async Task OnSearchInputChanged(string value) { _cts?.Cancel(); _cts?.Dispose(); _cts = new(); if (!string.IsNullOrWhiteSpace(value)) { suggestions = await searchService.GetSuggestionsAsync(value, _cts.Token); } } public void Dispose() { _cts?.Cancel(); _cts?.Dispose(); }
监听组件销毁自动取消(关键保障)
Blazor 会在组件被移除 dom 时调用 Dispose,但默认不自动触发取消。你需要显式绑定生命周期事件:
- 在
OnInitialized或OnParametersSet中注册:Disposal.Register(() => _cts?.Cancel()); - 或重写
Dispose(bool disposing)(推荐,尤其在继承ComponentBase的基类中统一处理) - 确保所有长期运行的异步操作都接受 token,并在
catch (OperationCanceledException)中正确退出,不更新状态
未响应取消的代码(如没传 token、忽略异常、仍调用 StateHasChanged())会导致“对象已释放”异常或 UI 错乱。
常见误区提醒
不要在非 async 方法中直接调用 token.ThrowIfCancellationRequested() —— 这会抛出异常但无法被 Blazor 的异步上下文捕获,可能中断渲染流程。
不要复用同一个
CancellationToken 实例跨多次独立操作 —— 它是一次性的,取消后不可重置。
不要依赖 IsCancellationRequested
轮询代替真正异步取消 —— 对 I/O 操作无效,且消耗 CPU。
基本上就这些。核心就两点:让异步调用真正“听” token,让 token 在组件消亡时“准时失效”。