Рассмотрим следующий фрагмент кода:
CancellationTokenSource cts0 = new CancellationTokenSource(), cts1 = new CancellationTokenSource();
try
{
var task = Task.Run(() => { throw new OperationCanceledException("123", cts0.Token); }, cts1.Token);
task.Wait();
}
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }
Из-за MSDN задача должна быть в состоянии Faulted
, потому что токен не совпадает с токеном исключения ( а также IsCancellationRequested
false
):
Если свойство token IsCancellationRequested возвращает false или если токен исключения не соответствует токену задачи, исключение OperationCanceledException рассматривается как обычное исключение, в результате чего задача переходит к состоянию Faulted.
Когда я запускаю этот код в консольном приложении с использованием .NET 4.5.2, я получаю задачу в состоянии Canceled
(суммарное исключение содержит неизвестный TaskCanceledExeption
, а не оригинал). И вся информация об исходном исключении теряется (сообщение, внутреннее исключение, пользовательские данные).
Я также заметил, что поведение Task.Wait
отличается от await task
в случае OperationCanceledException
.
try { Task.Run(() => { throw new InvalidOperationException("123"); }).Wait(); } // 1
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }
try { await Task.Run(() => { throw new InvalidOperationException("123"); }); } // 2
catch (InvalidOperationException ex) { Console.WriteLine(ex); }
try { Task.Run(() => { throw new OperationCanceledException("123"); }).Wait(); } // 3
catch (AggregateException ae) { Console.WriteLine(ae.InnerException); }
try { await Task.Run(() => { throw new OperationCanceledException("123"); }); } // 4
catch (OperationCanceledException ex) { Console.WriteLine(ex); }
Случаи 1
и 2
производят почти одинаковый результат (отличаются только StackTrace
), но когда я изменяю исключение на OperationCanceledException
, то получаю очень разные результаты: неизвестный TaskCanceledException
в случае 3
> без исходных данных и ожидаемых OpeartionCanceledException
в случае 4
со всеми исходными данными (сообщение и т.д.).
Итак, вопрос в том, содержит ли MSDN неправильную информацию? Или это ошибка в .NET? Или, может быть, я просто ничего не понимаю?