为什么发生TaskCanceledException?
我有以下testing代码:
void Button_Click(object sender, RoutedEventArgs e) { var source = new CancellationTokenSource(); var tsk1 = new Task(() => Thread1(source.Token), source.Token); var tsk2 = new Task(() => Thread2(source.Token), source.Token); tsk1.Start(); tsk2.Start(); source.Cancel(); try { Task.WaitAll(new[] {tsk1, tsk2}); } catch (Exception ex) { // here exception is caught } } void Thread1(CancellationToken token) { Thread.Sleep(2000); // If the following line is enabled, the result is the same. // token.ThrowIfCancellationRequested(); } void Thread2(CancellationToken token) { Thread.Sleep(3000); }
在线程方法中,我不会抛出任何exception,但是我会在启动任务的外部代码的try-catch
块中得到TaskCanceledException
。 为什么会发生这种情况, token.ThrowIfCancellationRequested();
的目的是什么token.ThrowIfCancellationRequested();
在这种情况下。 我相信只有在调用token.ThrowIfCancellationRequested();
才会抛出exceptiontoken.ThrowIfCancellationRequested();
在线程方法中。
我相信这是预期的行为,因为你正在跑步的竞争条件的变化。
从如何操作:取消任务及其子项 :
调用线程不会强行结束任务; 它只是表示要求取消。 如果任务已经运行,则由用户委托来注意请求并做出适当的响应。 如果在任务运行之前请求取消,那么用户委托永远不会执行,任务对象将转换为
Canceled
状态。
并从任务取消 :
您可以通过简单地从代表处返回来终止操作。 在很多情况下,这就足够了。 但是,以这种方式“取消”的任务实例将转换为
RanToCompletion
状态,而不是“Canceled
状态。
我的教育猜测是,当你在你的两个任务中调用.Cancel()
,在CancellationTokenSource
上调用.Cancel()
之前,其中一个(或两个)实际上并没有启动。 我敢打赌,如果你在任务开始和取消之间至less要等三秒钟,那么就不会抛出exception。 另外,您可以检查两个任务的.Status
属性。 如果我是正确的,当抛出exception时, .Status
属性应该至less读取其中的一个TaskStatus.Canceled
。
记住,开始一个新的Task
并不能保证正在创build一个新的线程。 它由TPL决定什么得到一个新的线程,什么是排队等待执行。