C#中如何取消前置异步任务,仅保留最后一次执行结果更新UI?
解决异步任务重复调用导致UI闪烁的问题
这个场景在高频触发的异步操作里特别常见,核心思路就是取消或忽略之前未完成的异步任务,只让最后一次调用的结果更新UI。我们可以借助CancellationTokenSource来实现这个需求,具体方案如下:
1. 新增取消令牌源字段
在你的类中添加一个私有字段,用来跟踪当前正在执行的异步任务的取消令牌:
private CancellationTokenSource _currentDescriptionCts;
2. 修改DisplayShortDescription方法
每次调用方法时,先取消之前未完成的任务,再创建新的令牌,最后在异步操作完成后判断是否要执行UI更新:
private async void DisplayShortDescription(object parameter) { var targetId = (int)parameter; // 取消之前未完成的任务 _currentDescriptionCts?.Cancel(); // 创建新的取消令牌源,用using确保资源被正确释放 using var newCts = new CancellationTokenSource(); _currentDescriptionCts = newCts; try { // 如果你的FindDescription方法支持取消,建议传入令牌终止不必要的操作 var description = await FindDescription(targetId, newCts.Token); // 只有当前令牌未被取消(说明这是最后一次调用),才更新UI if (!newCts.IsCancellationRequested) { ShortDescription = description.ShortDescription; CurrentDescriptionId = targetId; } } catch (OperationCanceledException) { // 任务被取消,无需做额外处理 } }
3. 适配FindDescription方法(可选但推荐)
如果FindDescription是IO密集型操作(比如调用API、查询数据库),建议让它接受CancellationToken参数,这样能真正取消正在执行的异步操作,避免浪费资源:
private async Task<DescriptionModel> FindDescription(int id, CancellationToken token) { // 示例:调用API时传入令牌 using var httpClient = new HttpClient(); var response = await httpClient.GetAsync($"https://your-api/descriptions/{id}", token); return await response.Content.ReadFromJsonAsync<DescriptionModel>(token); }
原理说明
- 每次触发
DisplayShortDescription时,先取消之前的CancellationTokenSource,这样之前的任务要么被直接终止(如果支持取消),要么在完成后检查到IsCancellationRequested为true,跳过UI更新。 - 最后一次调用的任务不会被后续调用取消,所以它的
IsCancellationRequested会保持false,最终执行UI更新代码。
内容的提问来源于stack exchange,提问作者Nikita Goncharuk
相关产品推荐
相关产品推荐

