Вообще вы, конечно правы в том, что async — это не панацея, и переводить решение на async просто потому что так сейчас модно, скорее всего не стоит. Однако, если ASP.NET решение упирается в пул потоков стоит наряду с увеличением пула рассмотреть вариант, при котором на hot path все вызовы будут полностью асинхронными.
Кроме того, набирают популярность managed решения, в которых у юзеров нет доступа к размеру пула потоков.
Я бы смотрел на async/await в ASP.NET так: микрософт предложил нам легкий способ работы с асинхронным кодом, который позволяет малой кровью подготовиться к хайлоаду «из коробки». По началу, он был кривой и косой, но уже в ASP.NET Core с ним стало вполне приятно работать и почти все известные проблемы убрали.
Кстати, поделитесь опытом: как вы с помощью PerfView пришли к выводу, что при использовании async/await сильный оверхед?
И еще вопрос:
Если же они работают медленно (>100мс) — на сервер никакой серьёзной нагрузки всё равно не создать
Всё правильно. Здесь отвязывается от контекста Task, который создается в StartWork, но Task, возвращаемый Task.Delay() всё еще привязан к контексту. Если перенести ConfigureAwait(false) в MyDelay, то дедлока не будет.
ConfigureAwait(false) вообще отвязывает операцию от контекста синхронизации и отправляет ее в пул потоков. SynchronizationContext.Current становится равным null.
После ConfigureAwait(false) снимаются все ограничения наложенные контекстом ранее.
Кроме того, набирают популярность managed решения, в которых у юзеров нет доступа к размеру пула потоков.
Я бы смотрел на async/await в ASP.NET так: микрософт предложил нам легкий способ работы с асинхронным кодом, который позволяет малой кровью подготовиться к хайлоаду «из коробки». По началу, он был кривой и косой, но уже в ASP.NET Core с ним стало вполне приятно работать и почти все известные проблемы убрали.
Кстати, поделитесь опытом: как вы с помощью PerfView пришли к выводу, что при использовании async/await сильный оверхед?
И еще вопрос:
Можете пояснить: почему не создать?
Справедливо. Поэтому Клэри и советует использовать ConfigureAwait (false) в библиотеках.
Всё правильно. Здесь отвязывается от контекста Task, который создается в StartWork, но Task, возвращаемый Task.Delay() всё еще привязан к контексту. Если перенести ConfigureAwait(false) в MyDelay, то дедлока не будет.
(2) Спасибо, интересно. Почитаю.
После ConfigureAwait(false) снимаются все ограничения наложенные контекстом ранее.
Отдельное спасибо за ссылку на Клэри :) Этот пост я как-то пропустил(