Как правильно отменить асинхронный запрос

.net c# entity-framework entity-framework-6 wpf

Вопрос

Это следующий вопрос к этому вопросу .

Я пытаюсь загрузить данные из моей базы данных, которые занимают 5-10 секунд, но я хочу, чтобы графический интерфейс оставался отзывчивым, а также он должен быть отменен.

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;

Я пробовал несколько вещей, но я просто не могу заставить это работать правильно, это просто загружает список, и все это, я не могу отменить это.

Где ошибка в этом?

Принятый ответ

Спасибо, что вызвали это. В настоящее время реализация этого асинхронного API в EF опирается на базовый поставщик ADO.NET для оценки отмены, но SqlDataReader.ReadAsync имеет некоторые ограничения, и мы заметили, что во многих случаях он не отменяется сразу после запроса отмены. У нас есть ошибка, которую мы рассматриваем для исправления в RTM EF6, которая заключается в представлении наших собственных проверок на запросы аннулирования между чтениями строк внутри методов EF.

В то же время вы можете обойти это ограничение, используя ForEachAsync (), чтобы добавить элементы в список и проверить каждую строку, например (не полностью протестировано):

    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;
    }


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему