简体   繁体   English

使用CancellationTokenSource取消先前的异步任务

[英]Canceling the previous Async Task using CancellationTokenSource

I need to implement async task cancel. 我需要实现async任务取消。 I know that CancellationTokenSource would help me in achieving that. 我知道CancellationTokenSource将帮助我实现这一目标。 But I'm unable to find a proper way. 但是我找不到合适的方法。

I have a search textbox, whenever a user types in textbox, for each textchanged event I call GetStocks method as shown below, 我有一个搜索文本框,每当用户在文本框中键入内容时,对于每个textchanged事件,我都会调用GetStocks方法,如下所示,

public async Task GetStocks()
{
    var stockings = new List<Services.Models.Admin.SiteStockingLevelsModel>();
    IsBusy = true;
    cts?.Cancel();
    cts = new CancellationTokenSource();
    await Task.Run(() => { CreateStockingCollection(); });
    ValidateMaterials();
    IsBusy = false;
}

The CreateStockingCollection method is as shown below, CreateStockingCollection方法如下所示,

private void CreateStockingCollection()
{
    var stockings = _siteStockingLevelsService.GetSiteInventoryLevels(SiteId);
    CreateStockingLevelCompareCollection(stockings);
    StockingLevels =
        _mapper.Map<TrulyObservableCollection<SiteStockingLevelsModel>>(stockings);            

    ((INotifyPropertyChanged)StockingLevels).PropertyChanged +=
        (x, y) => CompareStockingChanges();
    CompareStockingChanges();
}

My requirement here is, 我的要求是
Example Suppose user wants to type "Abc". 示例假设用户要键入“ Abc”。 When user types "A" the GetStocks method will be called, immediately the user enters "b" the again the get stocks methods will be called, in this case i want to cancel the previous GetStocks task called with letter "A". 当用户键入“ A”时,将调用GetStocks方法,立即用户输入“ b”,将再次调用get stocks方法,在这种情况下,我想取消以前用字母“ A”调用的GetStocks任务。

One of the best practices of the async programming in .Net is Async all the way . .Net中异步编程的最佳实践之一是Async all way Looks like your method isn't async-based, neither does it accept CancellationToken . 看起来您的方法不是基于异步的,也不接受CancellationToken You need to add it to your method, in other way only Task.Run will try to cancel your task, which wouldn't work well. 您需要将其添加到您的方法中, Task.Run只有Task.Run会尝试取消您的任务,但效果不佳。

Also, the only creation of the CancellationTokenSource isn't enough - you need to use it's .Token property in your code - this would exactly that token: 另外,仅创建CancellationTokenSource是不够的-您需要在代码中使用它的.Token属性-这恰好是该令牌:

await Task.Run(() => { CreateStockingCollection(); }, cts.Token);

Cancellation is cooperative, so you you need to pass it to your own code and have it respond to that token: 取消是协作的,因此您需要将其传递给自己的代码并使它响应该令牌:

public async Task GetStocks()
{
  var stockings = new List<Services.Models.Admin.SiteStockingLevelsModel>();
  IsBusy = true;
  cts?.Cancel();
  cts = new CancellationTokenSource();
  var token = cts.Token;
  await Task.Run(() => { CreateStockingCollection(token); });
  ValidateMaterials();
  IsBusy = false;
}

private void CreateStockingCollection(CancellationToken token)
{
  var stockings = _siteStockingLevelsService.GetSiteInventoryLevels(SiteId, token);
  CreateStockingLevelCompareCollection(stockings);
  StockingLevels =
      _mapper.Map<TrulyObservableCollection<SiteStockingLevelsModel>>(stockings);            

  ((INotifyPropertyChanged)StockingLevels).PropertyChanged +=
      (x, y) => CompareStockingChanges();
  CompareStockingChanges();
}

Here I'm passing it to GetSiteInventoryLevels , which sounds like that would be the long-running part of this work. 在这里,我将其传递给GetSiteInventoryLevels ,这听起来像是这项工作的长期工作。 GetSiteInventoryLevels must now take the CancellationToken and pass it along to whatever APIs it's using. 现在, GetSiteInventoryLevels必须获取CancellationToken并将其传递给正在使用的任何API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM