Нередко люди думают, что при использовании async-ожидания задействованы несколько потоков, в то время как на самом деле это не так, если вы не указали это.
Прочитано Eric Lippert about async-await искать где-то посередине для асинхронного ожидания.
Он сравнивает асинхронные ожидания с поваром: при поджаривании хлеба он может подождать, пока хлеб не поджарится перед кипячением воды для чая и яиц. Было бы более эффективно, если бы он начал кипятить воду, а затем повернуть назад, чтобы узнать, поджарен ли хлеб.
То же самое происходит в вашем коде. Во время вашего ждут task.Delay ваш поток не начинает ждать. Вместо этого он поднимается вверх по стеку вызовов, чтобы узнать, не ожидает ли один из вызывающих абонентов (кто все должен быть асинхронным!), И таким образом может продолжить обработку без результата своих вызовов. Через некоторое время он вернется, чтобы узнать, завершен ли Task.Delay и продолжает ли следующий оператор, где генерируется исключение.
Обратите внимание, что в этом сценарии задействован только один поток. Захват исключений выполняется как все остальные исключения. Хотя зрелище может проверять стек вызовов, он не уверен, какие части кода выполняются, а какие нет. В этом отношении нет большой разницы с не-асинхронным ожиданием
Да, вы правы. На самом деле, я прочитал вашу статью, прежде чем я разместил здесь. Проблема в том, что мне нужно написать метод, чтобы принять экземпляр Action в качестве параметра и выполнить его с помощью задачи. Я не нашел способ избежать необработанных исключений, из-за которых мой код разбился. – Wang
@Wang: Если тип * имеет * действие 'Action' (синхронно), а реализация * имеет * асинхронную, что является очень редкой позицией, то вам просто нужно поймать все исключения в пределах вашего выражения лямбды. –