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</strong> 实例跨多次独立操作 —— 它是一次性的,取消后不可重置。<br>
<strong>不要依赖 <code>IsCancellationRequested
轮询代替真正异步取消 —— 对 I/O 操作无效,且消耗 CPU。
基本上就这些。核心就两点:让异步调用真正“听” token,让 token 在组件消亡时“准时失效”。
