8

Я пытаюсь отложить обработку метода (SubmitQuery() в примере), вызванного из события клавиатуры в WinRT, до тех пор, пока не будет никаких дополнительных событий для период времени (500 мс в этом случае).TaskCanceledException при вызове Task.Delay с CancellationToken в событии с клавиатурой

Я хочу, чтобы функция SubmitQuery() запускалась, когда я думаю, что пользователь закончил печатать.

Используя следующий код, я продолжаю получать System.Threading.Tasks.TaskCanceledException, когда Task.Delay (500, cancelationToken.Token); называется. Что я делаю неправильно здесь, пожалуйста?

CancellationTokenSource cancellationToken = new CancellationTokenSource(); 

private async void SearchBox_QueryChanged(SearchBox sender, SearchBoxQueryChangedEventArgs args) 
{ 

     cancellationToken.Cancel(); 
     cancellationToken = new CancellationTokenSource(); 

    await Task.Delay(500, cancellationToken.Token); 

    if (!cancellationToken.IsCancellationRequested) 
    { 
     await ViewModel.SubmitQuery(); 
    } 
} 

ответ

11

Этого следовало ожидать. Когда вы отмените старый Delay, он будет вызывать исключение; вот как работает отмена. Вы можете положить простой try/catch вокруг Delay, чтобы поймать ожидаемое исключение.

Обратите внимание, что если вы хотите использовать логику, основанную на времени, Rx более естественна, чем async.

+0

могли бы вы предоставить ссылку на некоторые ресурсы о том, как Rx лучше подходит для повременной логика – Anupam

+2

@Anupam: Это из моего собственного опыта. –

25

Если вы добавили ContinueWith() с пустым действием, исключение не выбрасывается.

await Task.Delay(500, cancellationToken.Token).ContinueWith(tsk => { }); 
+4

Это потрясающе, спасибо. Сохраняет действительно уродливый код try/catch :) –

+1

Спасибо за это! Очень раздражает в отладчике, даже если он пойман. Я думаю, что в этих ситуациях «.Delay» мы ожидаем **, что токен должен быть отменен, поэтому исключение не должно даже подниматься/ломаться, и это исправлено совершенно. –