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();防止残留
示例(搜索建议):
这是一款使用jquery制作的带商品分类侧边栏列表的商城导航菜单。该商城菜单兼容ie8浏览器。用户可以通过点击左侧的下拉菜单来查看各种商品的列表,非常实用和方便。 使用方法 在页面中引入样式文件style.css和jquery.min.js文件。
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 在组件消亡时“准时失效”。









