2013-08-06 2 views
2

Это вопрос до this question.Как отменить асинхронный запрос в правильном направлении

Я пытаюсь загрузить данные из моей базы данных, которые занимают 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; 

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

Где ошибка?

+1

Когда вы говорите «Я не могу отменить это», что на самом деле происходит, когда вы говорите «CancellationTokenSource» отменить? –

+0

Nothings случается, поскольку у меня есть концепция, стоящая за этим, она должна генерировать исключение, если еще есть задача, выполняемая с этим токеном, но этого не происходит. – Staeff

+0

Что такое 'ToListAsync'? Из небольшого количества поисковых запросов я не могу найти его в составе MSDN или что-то в этом роде. Может быть, вы написали его, и он содержит ошибку, так что токен не применяется правильно? –

ответ

3

Спасибо, что принесли это. В настоящее время реализация этого асинхронного API в EF опирается на базовый поставщик ADO.NET для оценки отмены, но SqlDataReader.ReadAsync имеет некоторые ограничения, и мы заметили, что во многих случаях он не отменяется сразу после запроса отмены. У нас есть a bug, который мы рассматриваем для исправления в 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; 
    } 
+0

Я пробовал это сейчас, и он работает, но только после того, как данные загружены (проверено с помощью wirehark все данные загружены, но заполнение списка отменяется). Также я думаю, что 'ForEachAsync' также должен быть вызван с помощью' CancellationToken' => 'source.ForEachAsync (..., токена)', но он выглядит как 'ForEachAsync' и не реализует шаблон отмены в правильном направлении, потому что данные все еще загружаются и не генерируют исключения. – Staeff

+0

Ошибка, о которой я упомянул, заключается в добавлении запросов на проверку отмены в ForEachAsync, чтобы часть была устранена, когда мы исправляем ошибку. Другим аспектом, который интересен, является то, что, поскольку в EF6 мы буферизируем результаты запроса по умолчанию, загрузка datareader (т. Е. Вызовы в ReadAsyc) происходит на одном уровне ниже, прежде чем мы начнем материализовывать результаты. Я добавлю эту деталь к ошибке, чтобы мы ее рассмотрели при исправлении ошибки. – divega

+0

Кстати, чтобы избежать полных результатов от загрузки, вы можете добавить .AsStreaming() в запрос. Это будет иметь другие последствия, например. потоковые запросы несовместимы с функцией отказоустойчивости соединения. – divega

 Смежные вопросы

  • Нет связанных вопросов^_^