如何以正确的方式取消异步查询

这是对这个问题的后续问题 。

我正在尝试从我的数据库加载数据,这需要5-10秒,但我希望GUI保持响应,并且它应该是可取消的。

private CancellationTokenSource _source; public IEnumerable Measurements { get { ... } set { ... } } private async void LoadData() { _source = new CancellationTokenSource(); using (var context = new TraceContext()) { Measurements = null; Measurements = await context.Measurements.ToListAsync(_source.Token); } } private void Cancel() { if (_source != null) _source.Cancel(); } public RelayCommand ReloadCommand { get { return _reloadCommand ?? (_reloadCommand = new RelayCommand(Reload)); } } private RelayCommand _reloadCommand; public RelayCommand CancelCommand { get { return _cancelCommand ?? (_cancelCommand = new RelayCommand(Cancel)); } } private RelayCommand _cancelCommand; 

我已经尝试了一些东西,但是我无法让它正常工作,这只是加载List而且那就是全部,我无法取消它。

这个错误在哪里?

谢谢你提出这个问题。 目前,EF中此异步API的实现依赖于底层ADO.NET提供程序来取消,但SqlDataReader.ReadAsync有一些限制,我们观察到在许多情况下,在请求取消时不会立即取消。 我们正在考虑修复EF6 RTM中的错误 , 该错误是关于在EF方法内的行读取之间引入我们自己的取消请求检查。

同时,您可以通过使用ForEachAsync()将项添加到列表并检查每一行来解决此限制,例如(未经过全面测试):

  public async static Task> MyToListAsync( this IQueryable source, CancellationToken token) { token.ThrowIfCancellationRequested(); var list = new List(); await source.ForEachAsync(item => { list.Add(item); token.ThrowIfCancellationRequested(); }); return list; }