取消自动完成字段的任务不会取消以前的所有任务

本文关键字:任务 取消 字段 | 更新日期: 2023-09-27 18:06:24

我有一个搜索方法,它向UI返回搜索建议。每当用户在搜索框中输入一个新字符时,这个方法就会被触发。

我已经添加了一些取消代码来取消以前的搜索请求。这是有效的,但不是所有的时间。
private CancellationTokenSource cancellationTokenSource;
private async Task UserSearch(string searchCriteria)
{
    Debug.WriteLine("Searching for {0}....", searchCriteria);
    try
    {
        var cts = new CancellationTokenSource();
        this.Suggestions = await this.SearchAsync(searchCriteria, cts.Token);
    }
    catch (OperationCanceledException)
    {
        Debug.WriteLine("Search({0}) cancelled", searchCriteria);
    }
}
private async Task<IList<string>> SearchAsync(string searchCriteria, CancellationToken cancelToken)
{
    CancellationTokenSource previousCts = this.cancellationTokenSource;
    CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
    this.cancellationTokenSource = linkedCts;
    // if previous task running cancel it
    if (previousCts != null)
    {
        previousCts.Cancel();
    }
    linkedCts.Token.ThrowIfCancellationRequested();
    List<string> results =
        (await this.searchProvider.SearchAsync(searchCriteria, linkedCts.Token)).ToList();
    Debug.WriteLine("Search({0}) returned {1} records", searchCriteria, results.Count);
    linkedCts.Dispose();
    this.cancellationTokenSource = null;
    return results;
}
例如

。我得到以下调试消息:

SearchTerm changing to: Di 
Searching for Di....
SearchTerm changing to: Dia
Searching for Dia....
Search(Di) cancelled
SearchTerm changing to: Diap
Searching for Diap....
Search(Diap) returned 323 records
Search(Dia) returned 3230 records

正如你所看到的,第一个搜索被取消了,但第二个没有,它在最后一个搜索之后返回,给用户不正确的结果。

我如何确保以前的任务总是被取消?

取消自动完成字段的任务不会取消以前的所有任务

我想你可能把你的解决方案复杂化了一点。您所需要做的就是查看是否有正在进行的尚未取消的现有操作,并将其取消。然后执行新的搜索。没有测试过,但是我认为这个应该可以。

private CancellationTokenSource cancellationTokenSource;
private async Task UserSearch(string searchCriteria)
{
    Debug.WriteLine("Searching for {0}....", searchCriteria);
    try
    {       
        if(cancellationTokenSource != null && 
           !cancellationTokenSource.IsCancellationRequested)
        {
            cancellationTokenSource.Cancel();
        }
        cancellationTokenSource = new CancellationTokenSource();
        this.Suggestions = await this.searchProvider.SearchAsync(searchCriteria, linkedCts.Token);
        Debug.WriteLine("Search({0}) returned {1} records", searchCriteria, results.Count);
    }
    catch (OperationCanceledException)
    {
        Debug.WriteLine("Search({0}) cancelled", searchCriteria);
    }
}

您取消之前的查询太晚了,请尽快查询(直接在接收到用户输入后,而不是在下一个查询中)

我想问题是多线程访问this.cancellationTokenSource。如果说线程2取消线程1太晚了(searchProvider。SearchAsync已完成)。cancellationTokenSource可以在赋值后被清除(即线程2执行this)。cancellationTokenSource = linkedCts;之后的线程1调用this。cancellationTokenSource = null;)。这将有效地完全禁止取消线程2

因此,你最好在开始下一个搜索之前取消一个搜索,就像@Ned Stoyanov的建议