使用 CancellationTokenSource 取消之前的异步任务
Canceling the previous Async Task using CancellationTokenSource
我需要执行 async
任务取消。我知道 CancellationTokenSource
会帮助我实现这一目标。但是我找不到合适的方法。
我有一个搜索文本框,每当用户在文本框中键入内容时,对于每个文本更改事件,我都会调用 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 方法,在这种情况下我想取消之前的 GetStocks
用字母 "A".
调用的任务
.Net 中异步编程的最佳实践之一是 Async all the way。看起来你的方法不是基于异步的,它也不接受 CancellationToken
。您需要将它添加到您的方法中,否则只有 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。
我需要执行 async
任务取消。我知道 CancellationTokenSource
会帮助我实现这一目标。但是我找不到合适的方法。
我有一个搜索文本框,每当用户在文本框中键入内容时,对于每个文本更改事件,我都会调用 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 方法,在这种情况下我想取消之前的 GetStocks
用字母 "A".
.Net 中异步编程的最佳实践之一是 Async all the way。看起来你的方法不是基于异步的,它也不接受 CancellationToken
。您需要将它添加到您的方法中,否则只有 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。