#c# #async-await #asp.net-core-mvc
#c# #асинхронное ожидание #asp.net-core-mvc
Вопрос:
Мы все знаем известное сообщение в блоге Стивена Клири о блокировке асинхронного кода. В MVC 5 следующий код блокируется при запросе Home/Index
:
public class HomeController : Controller
{
public string Index()
{
var model = AsyncMethod();
return model.Resu<
}
private async Task<string> AsyncMethod()
{
await Task.Run(() => Thread.Sleep(2000));
return "Hello";
}
}
Однако точно такой же код не приводит к взаимоблокировке в веб-приложении ядра MVC. Ответ возвращает привет. Почему? Позволяет ли ядро MVC запускать несколько потоков одновременно в одном контексте запроса? Устарела ли фраза «Не блокировать асинхронный код» при разработке в ядре MVC?
Ответ №1:
Почему?
ASP.NET Ядро расположено async
сверху вниз и рассчитано на максимальную скорость.
В рамках редизайна, ASP.NET команда смогла удалить все AspNetSynchronizationContext
полностью. Некоторые аспекты ASP.NET контекст запроса был перенесен в ядро .NET, а другие были просто удалены (например, HttpContext.Current
).
Позволяет ли ядро MVC запускать несколько потоков одновременно в одном контексте запроса?
Нет. Однако понятие «контекст запроса» больше не представлено контекстом синхронизации.
Устарела ли кодовая фраза Don’t Block on Async при разработке в ядре MVC?
Нет. Это не приведет к тупику на ASP.NET Ядро, но ты все равно не должен этого делать.
«Могу ли я заблокировать асинхронный код в ядре MVC?» Да. «Должен ли я блокировать асинхронный код в ядре MVC?» Нет.
Комментарии:
1. Для тех из вас, кто хотел бы получить более подробное объяснение, ознакомьтесь с этим сообщением в блоге Стивена — blog.stephencleary.com/2017/03 /. …
Ответ №2:
Этот код
await Task.Run(() => Thread.Sleep(2000));
возможно, это не очень удачный шаблон, но он не «блокирует» в том смысле, на который ссылается сообщение Стивена. Чтобы сравнить яблоки с яблоками, вам нужно будет сделать это:
private string BlockingAsyncMethod()
{
Task.Run(() => Thread.Sleep(2000)).Wait();
return "Hello";
}
Блокировка на Wait()
or .Result
— это большой запрет для MVC 5. Насколько мне известно, это все еще правильный совет для ядра MVC.
Комментарии:
1. Ваш пример не приводит к взаимоблокировке в ядре MVC. Я все еще получаю «Привет»
2. @Kapol блокирует!= взаимоблокировка. Блокировка относится к синхронному ожиданию результата операции. Взаимоблокировки иногда возникают, когда вы блокируете синхронно (
Wait()
например, с помощью) асинхронную операцию. Важно отметить, что даже при плохом шаблоне (синхронизация через асинхронность) взаимоблокировки возникают не всегда .3. Извини, Нейт, конечно, я имел в виду тупик. Дело в том, что, насколько я понимаю, мой пример всегда приводил к тупиковой ситуации в MVC 5, тогда как я не могу воспроизвести это поведение хотя бы один раз в ядре MVC.
4. Кроме того, изначально мой асинхронный метод вызывал асинхронную операцию MongoDB, которая, вероятно, очень близка к тому, что Стивен описал в своем блоге.