如何以正确的方式取消异步查询 [英] How to cancel an async query the right way

查看:117
本文介绍了如何以正确的方式取消异步查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个后续问题,这个问题

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

I'm trying to load data from my database which will take 5-10 seconds, but I want the GUI to stay responsive and also it should be cancellable.

private CancellationTokenSource _source;

public IEnumerable<Measurement> 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;

我已经尝试了一些事情,但是我无法让它正常工作,只需加载列表,这就是所有的,我不能取消这个。

I've tried a few things, but I just can't get this to work properly, this just loads the List and thats all, I can't cancel this.

这个错误在哪里?

推荐答案

感谢您提出来。目前,EF中的这个async API的实现依赖于底层的ADO.NET提供程序来取消它,但是SqlDataReader.ReadAsync有一些限制,我们已经观察到,在许多情况下,当请求取消时,它不会立即取消。我们正在考虑修改EF6 RTM中的一个错误,该错误是关于引入我们自己的检查EF读取之间的取消请求。

Thanks for bringing this up. Currently the implementation of this async API in EF relies on the underlying ADO.NET provider to honor cancellation, but SqlDataReader.ReadAsync has some limitations and we have observed that in many cases it won't cancel immediately when cancellation is requested. We have a bug that we are considering for fixing in EF6 RTM that is about introducing our own checks for the cancellation requests between row reads inside the EF methods.

同时,您可以通过使用ForEachAsync()将项目添加到列表并检查每一行,例如(未经彻底测试):

In the meanwhile you can workaround this limitation by using ForEachAsync() to add items to the list and check on every row, e.g. (not thoroughly tested):

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

这篇关于如何以正确的方式取消异步查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆