Я пытался выяснить, почему я получаю TaskCanceledException для небольшого количества асинхронного кода, который недавно начал плохо себя вести. Я сократил свою проблему до небольшого фрагмента кода, который заставляет меня чесать голову:

static void Main(string[] args)
{
    RunTest();
}

private static void RunTest()
{
    Task.Delay(1000).ContinueWith(t => Console.WriteLine("{0}", t.Exception), TaskContinuationOptions.OnlyOnFaulted).Wait();
}

Насколько мне известно, это должно просто остановиться на секунду, а затем закрыть. ContinueWith не будет вызываться (это относится только к моему фактическому варианту использования). Однако вместо этого я получаю TaskCanceledException и понятия не имею, откуда оно взялось!

7
Barguast 20 Фев 2015 в 19:38

2 ответа

Лучший ответ

Вы используете неправильные варианты продолжения задачи:

См. Следующую ссылку: https : //msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions%28v=vs.110%29.aspx

Он говорит: указывает, что задача продолжения должна быть запланирована только в том случае, если ее предшествующая задача вызвала необработанное исключение. Этот вариант не подходит для продолжений многозадачности.

2
Philip Stuyck 20 Фев 2015 в 16:46

Как ребята сказали выше, для этого вызова требуется только antecedent-task в статусе ошибки, в противном случае будет выброшено TaskCanceledException, для этого конкретного случая вы можете обобщить ContinueWith для обработки всех статусов:

await Task.Delay(1000).ContinueWith(
    task => 
        {
            /* take into account that Canceled-task throw on next row the TaskCancelledException */

            if (!task.IsFaulted) {
                return;
            }

            Console.WriteLine("{0}", task.Exception);
            // do smth like 'throw task.Exception.InnerException'
        });
1
vladimir 20 Окт 2019 в 01:30