Итак, у меня есть поле со списком в моем пользовательском интерфейсе, которое в SelectionChanged асинхронно переходит в веб-службу, чтобы получить некоторую информацию, которая будет отображаться в пользовательском интерфейсе (с использованием новых ключевых слов C # 5 async / await). Я хочу отменить текущий асинхронный запрос перед отправкой нового; например, если пользователь использует клавиатуру для быстрого просмотра всех элементов поля со списком, событие SelectionChanged может запускаться несколько раз (генерируя несколько асинхронных запросов) до того, как вернется даже первый асинхронный запрос.
Итак, моя асинхронная функция, которая вызывается из события SelectionChanged поля со списком, выглядит так:
public async Task<Connections> ConnectionsAsync()
{
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
}
Где Connections - это свойство, которое отключается и попадает в веб-службу. Итак, поскольку CancellationTokenSource не может быть повторно использован после отмены, я думаю сделать это:
public async Task<Connections> ConnectionsAsync()
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
}
Проблема, однако, в том, что иногда я вызываю Cancel (), когда не запущена асинхронная команда (например, при первом вызове этой функции); поэтому, если я подключу какие-либо обработчики событий отмены, они будут вызваны, даже до того, как я сделаю асинхронный запрос.
Есть ли способ проверить, запущен ли уже асинхронный запрос? Кроме меня, делаю что-то вроде:
public async Task<Connections> ConnectionsAsync()
{
if (_runningAsyncCommand)
_cancellationTokenSource.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
_runningAsyncCommand = true;
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
_runningAsyncCommand = false;
}
У меня есть несколько асинхронных функций, которые все используют один и тот же CancellationTokenSource, поэтому мне пришлось бы реализовать эту «сантехнику» во всех этих функциях. Это лучший подход? Или есть способ лучше?
Кроме того, если я открываю _cancellationTokenSource публично, чтобы другие классы могли регистрировать с ним делегаты отмены, как лучше всего «передать» эти делегаты в новый CancellationTokenSource, поскольку я каждый раз создаю новый?
Заранее спасибо!