Могу ли я заблокировать асинхронный код в MVC Core?
Мы все знаем знаменитое сообщение в блоге относительно блокировки асинхронного кода Стивеном Клири. В MVC 5 следующий код блокируется при запросе Home/Index
:
public class HomeController : Controller
{
public string Index()
{
var model = AsyncMethod();
return model.Result;
}
private async Task<string> AsyncMethod()
{
await Task.Run(() => Thread.Sleep(2000));
return "Hello";
}
}
Однако тот же самый код не заторможен в веб-приложении MVC Core. Ответ возвращает Hello. Зачем? Поддерживает ли MVC Core несколько потоков одновременно работать в одном контексте запроса? Является ли фраза Не блокировать асинхронный код устаревшей при разработке в MVC Core?
Ответы
Ответ 1
Почему?
Ядро ASP.NET async
сверху вниз, и оно предназначено для максимальной скорости.
В рамках редизайна команда ASP.NET смогла полностью удалить весь AspNetSynchronizationContext
. Некоторые аспекты контекста запроса ASP.NET были перенесены в основное .NET, а другие были просто удалены (например, HttpContext.Current
).
Поддерживает ли MVC Core несколько потоков одновременно в одном контексте запроса?
Нет. Однако понятие "контекст запроса" больше не представлено контекстом синхронизации.
Является ли "Не блокировать фразу" Асинхронный код "устаревшей при разработке в MVC Core?
Нет. Он не будет зациклен на ядре ASP.NET, но вы все равно не должны этого делать.
"Могу ли я заблокировать асинхронный код в MVC Core?" Да. "Должен ли я блокировать асинхронный код в MVC Core?" Нет.
Ответ 2
Этот код
await Task.Run(() => Thread.Sleep(2000));
не может быть отличным шаблоном, но он не "блокирует" в том же смысле, что и ссылка Стивена. Чтобы сравнить яблоки с яблоками, вам нужно будет сделать это:
private string BlockingAsyncMethod()
{
Task.Run(() => Thread.Sleep(2000)).Wait();
return "Hello";
}
Блокировка на Wait()
или .Result
является большим no-no для MVC 5. Насколько мне известно, это все еще правильный совет для MVC Core.