Поскольку лямбда-выражение является асинхронным, оно может выполняться в любом потоке, который вызывает Value, и выражение будет выполняться в контексте.
Лямбда может быть запущена из любого потока (если вы не заботитесь о том, какие типы потоков вы позволяете получить доступ к значению Lazy
), и, как таковой, он будет запускаться в контексте из этой темы. Это не , потому что это асинхронный , было бы верно, даже если бы он был синхронным, если бы он выполнялся в контексте любого потока, вызывающего его.
Насколько я понимаю, поток приходит в FetchPerson и застревает в исполнении Lamda.
Лямбда является асинхронной , поэтому она (при правильной реализации) вернется почти немедленно. Вот что значит быть асинхронным, так как он не будет блокировать вызывающий поток.
Это действительно плохо? Какие последствия?
Если вы неправильно внедрили свой асинхронный метод и долго выполняете синхронную работу, то да, вы блокируете этот поток / контекст. Если нет, то нет.
Кроме того, по умолчанию все продолжения в ваших асинхронных методах будут выполняться в исходном контексте (если он вообще имеет SynchonrizationContext
). В вашем случае ваш код почти наверняка не полагается на повторное использование этого контекста (поскольку вы не знаете, какие контексты может иметь ваш вызывающий объект, я не могу представить, что вы написали остальную часть кода для его использования). Учитывая это, вы можете вызывать .ConfigureAwait(false)
для всего, что вы await
, чтобы не использовать текущий контекст для этих продолжений. Это просто незначительное улучшение производительности, чтобы не тратить время на планирование работы в исходном контексте, ожидание чего-либо еще, что ему нужно, или заставлять что-либо еще ждать этого кода, когда это не нужно.
В качестве решения автор предлагает создать задание: [...] Это действительно правильно?
Это ничего не сломает. Это запланирует работу для выполнения в потоке пула потоков, а не в исходном контексте. Это будет иметь дополнительные издержки для начала. Вы можете сделать примерно то же самое с меньшими накладными расходами, просто добавив ConfigureAwait(false)
ко всему, что вы await
.
Это операция ввода-вывода, но мы крадем поток ЦП из Threadpool.
Этот фрагмент запустит операцию ввода-вывода в потоке пула потоков. Поскольку метод все еще асинхронный, он вернет его в пул, как только он его запустит, и получит новый поток из пула, чтобы снова запускаться после каждого ожидания. Последнее, вероятно, подходит для этой ситуации, но перемещение кода для запуска начальной асинхронной операции в поток пула потоков просто добавляет накладные расходы без реального значения (поскольку это такая короткая операция, вы потратите больше усилий на планирование ее в потоке поток пула, чем просто запустить его).