And*_*rts 16 c# asynchronous cancellationtokensource windows-runtime cancellation-token
我试图延迟在WinRT中从键盘事件调用的方法(在示例中为SubmitQuery())的处理,直到一段时间内没有其他事件(在这种情况下为500毫秒).
我只想在我认为用户输入完成后运行SubmitQuery().
使用下面的代码,当Task.Delay(500,cancellationToken.Token)时,我不断收到System.Threading.Tasks.TaskCanceledException; 叫做.我在这做错了什么?
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Jer*_*gen 44
如果ContinueWith()
使用空操作添加,则不会抛出异常.异常被捕获并传递给该task.Exception
属性ContinueWith()
.但它可以帮助您避免编写试图/捕获代码的问题.
await Task.Delay(500, cancellationToken.Token).ContinueWith(tsk => { });
Run Code Online (Sandbox Code Playgroud)
Ste*_*ary 16
这是可以预料的.取消旧版时Delay
,会引发异常; 这就是取消的方式.你可以放一个简单的try
/ catch
围绕它Delay
来捕获预期的异常.
请注意,如果你想做这样的基于时间的逻辑,Rx比自然更适合async
.
抑制等待任务异常的另一种简单方法是将任务作为单个参数传递给Task.WhenAny
:
创建一个任务,该任务将在任何提供的任务完成后完成。
await Task.WhenAny(Task.Delay(500, token)); // Ignores the exception
Run Code Online (Sandbox Code Playgroud)
这种方法的一个问题是它没有清楚地传达其意图,因此建议添加注释。另一个是它会导致分配(因为 的params
签名Task.WhenAny
)。
注意:当 aTask
发生故障并且Exception
未直接或间接观察到它时,TaskScheduler.UnobservedTaskException
会在未来某个时刻(非确定性)触发此任务的事件。上面显示的技巧,使用该Task.WhenAny
方法,不观察任务Exception
,因此事件将被触发。在 的特定情况下Task.Delay(500, token)
,任务以取消状态完成,而不是以故障状态完成,因此无论如何它都不会触发事件。
我认为值得添加一个评论来说明为什么它会这样工作。
该文档实际上是错误的,或者对于方法的 TaskCancelledException 写得不清楚Task.Delay
。该Delay
方法本身永远不会抛出该异常。它将任务转移到取消状态,而到底引发异常的是await
。Task.Delay
这里使用什么方法并不重要。它与任何其他已取消的任务的工作方式相同,这就是取消的预期工作方式。这实际上解释了为什么添加延续会神秘地隐藏异常。因为它是由 引起的await
。