Когда использовать @await Html.PartialAsync в представлении в MVC 6

Я заметил в одном из блогов Скотта Хансельмана, что он использует следующий код в своих представлениях при использовании .Net 5 (MVC 6):

@await Html.PartialAsync("_LoginPartial")

vs.

@Html.Partial("_LoginPartial")

Есть ли какая-либо документация о том, когда какой из них следует использовать?


person RickJames    schedule 24.02.2015    source источник


Ответы (4)


На самом деле это довольно интересный вопрос и сценарий. В какой-то степени асинхронность — это новая мода (хотя на самом деле это не так уж и ново). В Entity Framework 6 появились асинхронные методы, и каждый... отдельный... фрагмент... документации... внезапно начал использовать асинхронность для всего. Я думаю, что мы видим немного то же самое здесь. MVC 6 поддерживает асинхронность для таких вещей, как частичный рендеринг, так что, боже мой, теперь мы все просто должны использовать асинхронность.

Async служит одной очень конкретной цели. Это позволяет вернуть активный поток в пул для выполнения других задач, пока текущая задача находится в состоянии ожидания. Ключевой частью этого является «состояние ожидания». Некоторые задачи просто несовместимы с асинхронностью. Работа с привязкой к ЦП, такая как сложный финансовый анализ, никогда не позволяет потоку переходить в состояние ожидания, поэтому все эффективно выполняется как синхронизация, даже если вы настроили ее как асинхронную. С другой стороны, вещи, связанные с задержкой в ​​сети (запрос ресурса из веб-API, запрос к базе данных и т. д.) или связанные с вводом-выводом (чтение/запись файлов и т. д.), могут иногда иметь периоды, когда поток ожидание завершения какого-либо другого процесса, прежде чем он продолжит обработку.

Что касается частичного рендеринга, единственная часть, которая не полностью связана с процессором, — это чтение самого файла представления из файловой системы. Хотя этого технически достаточно, чтобы сделать его подходящим для асинхронного режима, сколько времени на самом деле потребуется, чтобы прочитать текстовый файл, который, вероятно, не превышает 50 КБ. К тому времени, когда поток будет передан обратно в пул, вероятно, пришло время запросить его обратно, поэтому в этот момент вы фактически используете ресурсы более неэффективно.

Короче говоря, не попадайтесь в ловушку «это можно сделать асинхронно, поэтому я должен сделать это асинхронно». Каждое использование следует оценивать с точки зрения того, действительно ли в нем есть ценность. Async имеет много накладных расходов, и если вы говорите только о нескольких миллисекундах времени ожидания, это, вероятно, не стоит всех этих дополнительных накладных расходов.

person Chris Pratt    schedule 24.02.2015
comment
На самом деле await возвращает текущий поток, пока задача не завершится. Это не имеет ничего общего с состояниями ожидания. - person Stephen Cleary; 25.02.2015
comment
Во-первых, я не говорю конкретно о ключевом слове async, здесь я говорю об асинхронности в целом. Во-вторых, я понятия не имею, что означает ваше последнее утверждение. Это имеет прямое отношение к нахождению в состоянии ожидания. Поток не просто автоматически уступает. Он должен выполнять работу до тех пор, пока не будет ждать чего-то вне его контроля: данные передаются по сети, раскручивается жесткий диск и так далее. Как только он не ожидает этого, коду нужен поток обратно, чтобы завершить любую работу. - person Chris Pratt; 25.02.2015
comment
Крис, спасибо за хорошо продуманный ответ. Но я действительно ищу ответ, почему он используется в .net 5. Я понимаю, в чем разница между асинхронным и неасинхронным, но я все же хотел бы знать, есть ли причина, по которой он использует его для частичного. Согласно вашему ответу, он (Скотт Хансельман) использует его неправильно. - person RickJames; 27.02.2015
comment
Не обязательно неправильно. Рендеринг частичных файлов требует обращения к файловой системе. Файловая система имеет очередь, и в зависимости от того, что еще происходит на сервере в это время, может потребоваться время ожидания. Любая операция, которая предполагает ожидание, подходит для асинхронности, поэтому в этом отношении вполне допустимо иметь что-то вроде PartialAsync. Я хочу сказать, что в большинстве сред и ситуаций использование асинхронного рендеринга для партиала будет обречено на провал, и вы всегда должны оценивать конкретный сценарий при использовании асинхронного. Не используйте асинхронность только потому, что она есть. - person Chris Pratt; 27.02.2015
comment
просто хочу отметить: несколько миллисекунд на тысячу запросов — все еще хороший выигрыш. Тот факт, что веб-приложения выигрывают от асинхронности, во многом связан с одновременным обращением нескольких запросов к серверу. - person Bart Calixto; 07.04.2015
comment
Я не говорил, что это сэкономит вам всего несколько миллисекунд; Я говорил, что поток может не понадобиться только в течение нескольких миллисекунд. Если поток возвращается в пул только для того, чтобы быть запрошенным через несколько миллисекунд, это может фактически привести к тому, что все время рендеринга в целом увеличится, а это означает, что вашему серверу требуется больше времени, чем нужно для ответа. Опять же, каждое использование асинхронности должно быть оценено, чтобы убедиться, что оно действительно работает на вас, а не против вас. Если на вашем сервере есть SSD, то асинхронизация для частичных будет пустой тратой ресурсов. - person Chris Pratt; 08.04.2015
comment
Что касается частичного рендеринга, единственная часть, которая не полностью связана с процессором, — это чтение самого файла представления из файловой системы. Но представления могут вызывать компоненты представления, которые, в свою очередь, могут выполнять произвольные асинхронные операции? docs.asp.net/projects/mvc/en/ последний/представления/представление-компоненты.html - person ta.speot.is; 06.01.2016
comment
@ta.speot.is: Совершенно верно. Однако дело здесь не в этом. Если вы выполняете асинхронные операции, то да, используйте асинхронность, но проблема в том, что учебные пособия и тому подобное слишком часто не делают различия, и у менее информированных разработчиков создается впечатление, что вы должны просто использовать асинхронный режим, потому что это то, о чем учебник, книга, видео и т.п. сделал. Если вы просто визуализируете представление, делать это асинхронно, вероятно, неправильный подход. - person Chris Pratt; 06.01.2016
comment
Ох... кто-то переворачивает голову и рекомендует не использовать асинхронность для всего! Редкий случай стать свидетелем этого. - person usr; 27.09.2016
comment
@Chris, что, если у нас есть частичное представление и в нем есть помощник тега или компонент представления, который отправляет запросы в репозиторий. Думаю, в этом случае мы должны использовать RenderAsync для рендеринга этого частичного представления, не так ли? - person Sergey; 24.02.2018
comment
Да. Компоненты просмотра являются асинхронными, и если ваш частичный компонент делает что-либо асинхронным, он сам должен быть асинхронным. Честно говоря, вы, вероятно, будете использовать асинхронность чаще, чем нет. Я просто подчеркиваю, что в некоторых сценариях вам может быть лучше синхронизироваться, потому что большинство разработчиков на самом деле не думают об этом в каждом отдельном случае. - person Chris Pratt; 24.02.2018

Согласно документации ASP.NET MVC по частичным представлениям. https://docs.asp.net/en/latest/mvc/views/partial.html

Метод PartialAsync доступен для частичных представлений, содержащих асинхронный код (хотя код в представлениях обычно не рекомендуется):

Также примечание на странице.

Если ваши представления должны выполнять код, рекомендуется использовать компонент представления вместо частичного представления.

Таким образом, вы должны использовать Partial и избегать PartialAsync, и если вы обнаружите, что у вас есть PartialAsync, вы должны спросить себя, делаете ли вы что-то неправильно, возможно, вам следует вместо этого использовать ViewComponent или перенести логику из представления в контроллер.

person Fred    schedule 27.09.2016
comment
В настоящее время в asp.net core 2.1 в той же документации упоминается Использование синхронных эквивалентов не рекомендуется, поскольку существуют сценарии, в которых они блокируются. В будущих версиях не будет синхронных методов. - person Gqqnbig; 31.08.2018
comment
В ASP.NET 3.1 выдается предупреждение при использовании Partial вместо await .. PartialAsync, поэтому теперь нет дилеммы. - person Alexei - check Codidact; 01.01.2020

Что касается «ожидания Html.PartialAsync» — эта ссылка может вам помочь — http://aspnetwebstack.codeplex.com/workitem/601 (также следите за комментариями) (в чем именно была проблема раньше).

Я работаю над общедоступным веб-сайтом, созданным на MVC 6, и «ожидание Html.PartialAsync» быстрее, чем «Html.Partial», особенно когда представление содержит много компонентов.

Удаление «ожидания» из Html.PartialAsync, очевидно, не работает, и Html.PartialAsync выдает имя типа (например, «System.Threading.Tasks.Task`1[Microsoft.AspNet.Mvc.Rendering.HtmlString]») вместо фактического вида.

person Krishna Santosh Sampath    schedule 29.03.2015

Просто чтобы поддерживать ветку в актуальном состоянии для тех, кто посещает ее в эпоху ядра asp.net.

В настоящее время согласно документации:

Partial и RenderPartial являются синхронными эквивалентами PartialAsync и RenderPartialAsync соответственно. Синхронные эквиваленты не рекомендуются, поскольку существуют сценарии, в которых они взаимоблокируются. Синхронные методы планируется удалить в будущем выпуске.

Полное содержание: Частичные представления в ASP. NET Core

Чтобы понять, почему это проблема, вы можете взглянуть на эту запись на github:

https://github.com/aspnet/Mvc/issues/7083

Но если вкратце, то похоже, что синхронная версия Partial просто вызывает асинхронную версию с GetResult, и в некоторых сценариях это рецепт взаимоблокировок.

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

var result = htmlHelper.RenderPartialAsync(partialViewName, htmlHelper.ViewData.Model, viewData: null);
result.GetAwaiter().GetResult();
person mikus    schedule 27.07.2021