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

实时搜索开发咨询:重新运行前如何关闭任务?

解决实时搜索中取消旧异步任务的方案

嘿,这个场景我太熟了!用户快速输入搜索关键词时,旧的API请求还在慢悠悠跑着,等新的请求结果回来,旧结果反而抢着显示出来,完全不符合预期对吧?别担心,咱们用CancellationTokenSource就能完美解决这个问题,这是异步任务取消的标准做法,我给你一步步拆解:

核心思路

每次用户输入新的搜索词时,先取消正在执行的旧搜索任务,再启动新的任务。通过CancellationTokenSource来管理任务的生命周期,确保只有最新的搜索请求结果会被处理。

具体实现步骤

1. 添加任务取消源字段

在你的ViewModel类中,声明一个CancellationTokenSource字段,用来跟踪当前正在执行的搜索任务:

private CancellationTokenSource _searchCancellationSource;
private string searchPhrase;

2. 修改SearchPhrase的Setter逻辑

在属性的setter中,先取消旧任务,再创建新的取消源,最后启动新的搜索任务:

public string SearchPhrase {
    get => searchPhrase;
    set {
        SetProperty(ref searchPhrase, value);
        
        // 取消之前的搜索任务
        _searchCancellationSource?.Cancel();
        // 释放旧的取消源资源(可选,但推荐)
        _searchCancellationSource?.Dispose();
        // 创建新的取消源
        _searchCancellationSource = new CancellationTokenSource();
        
        // 重置UI状态
        RunOnMainThread(() => SearchResult.Clear());
        isAllFriends = false;
        currentPage = 0;
        
        // 启动新的搜索任务,传入取消令牌
        _ = LoadData(_searchCancellationSource.Token);
    }
}

3. 修改LoadData方法支持取消

让LoadData接受CancellationToken,并在关键节点检查取消状态,同时把令牌传递给API调用(如果你的API客户端支持取消的话,比如HttpClient):

private async Task LoadData(CancellationToken cancellationToken) {
    try {
        // 将取消令牌传递给API请求,让底层请求也能被取消
        var response = await connectionRepository.GetConnectAsync(searchPhrase, cancellationToken);
        
        // 检查任务是否已被取消,避免处理旧请求的结果
        cancellationToken.ThrowIfCancellationRequested();
        
        // 在主线程更新UI(确保操作安全)
        RunOnMainThread(() => {
            // 这里填充SearchResult列表的逻辑
            // 比如:SearchResult.AddRange(response.Data);
        });
    } catch (OperationCanceledException) {
        // 任务被取消属于正常流程,这里可以记录日志或者啥也不做
        System.Diagnostics.Debug.WriteLine("旧的搜索任务已被取消");
    } catch (Exception ex) {
        // 处理其他异常,比如网络错误
        System.Diagnostics.Debug.WriteLine($"搜索失败:{ex.Message}");
    }
}

4. 清理资源(重要)

在ViewModel销毁时,记得取消并释放CancellationTokenSource,避免内存泄漏:

public void Dispose() {
    _searchCancellationSource?.Cancel();
    _searchCancellationSource?.Dispose();
}

额外提醒

  • 确保你的API客户端(比如connectionRepository里的HTTP请求)支持CancellationToken,这样才能真正取消正在进行的网络请求,而不只是中断后续的结果处理。
  • 不要忽略OperationCanceledException,取消任务时必然会抛出这个异常,捕获它可以避免程序崩溃。
  • 如果你的搜索场景需要防抖(比如用户输入停顿后再发起请求),可以在setter里加个延迟,结合CancellationTokenSource一起使用,进一步减少无效的API请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:27:03