繁体   English   中英

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

[英]Canceling the previous Async Task using CancellationTokenSource

我需要实现async任务取消。 我知道CancellationTokenSource将帮助我实现这一目标。 但是我找不到合适的方法。

我有一个搜索文本框,每当用户在文本框中键入内容时,对于每个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;
}

CreateStockingCollection方法如下所示,

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

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

我的要求是
示例假设用户要键入“ Abc”。 当用户键入“ A”时,将调用GetStocks方法,立即用户输入“ b”,将再次调用get stocks方法,在这种情况下,我想取消以前用字母“ A”调用的GetStocks任务。

.Net中异步编程的最佳实践之一是Async all way 看起来您的方法不是基于异步的,也不接受CancellationToken 您需要将其添加到您的方法中, Task.Run只有Task.Run会尝试取消您的任务,但效果不佳。

另外,仅创建CancellationTokenSource是不够的-您需要在代码中使用它的.Token属性-这恰好是该令牌:

await Task.Run(() => { CreateStockingCollection(); }, cts.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();
}

在这里,我将其传递给GetSiteInventoryLevels ,这听起来像是这项工作的长期工作。 现在, GetSiteInventoryLevels必须获取CancellationToken并将其传递给正在使用的任何API。

暂无
暂无

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

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