Ответ 1
Использование await Task.Run
для создания "async" WebApi - плохая идея - вы по-прежнему будете использовать поток и даже тот же пул потоков, для запросов.
Это приведет к некоторым неприятным моментам, описанным в хороших подробностях здесь:
- Дополнительное (ненужное) переключение потоков в поток потока Task.Run. Аналогично, когда этот поток заканчивает запрос, он должен введите контекст запроса (который не является фактическим переключателем потока, но имеет накладные расходы).
- Создан дополнительный (ненужный) мусор. Асинхронное программирование - это компромисс: вы получаете повышенную отзывчивость за счет более высоких использование памяти. В этом случае вы создаете больше мусора для асинхронные операции, которые совершенно не нужны.
- Эвристика пула потоков ASP.NET отбрасывается Task.Run "неожиданно" заимствует поток пула потоков. У меня нет много опыт здесь, но мой инстинкт кишки говорит мне, что эвристика должен хорошо восстановиться, если неожиданная задача действительно короткая и не обрабатывайте его так же элегантно, если неожиданная задача длится более двух секунд.
- ASP.NET не может завершить запрос раньше, то есть, если клиент отключится или время ожидания запроса. В синхронном случае, ASP.NET знал поток запросов и мог прервать его. в асинхронный случай, ASP.NET не знает, что пул вторичных потоков thread - это "для" этого запроса. Это можно исправить, используя аннулирование токенов, но это выходит за рамки этого сообщения в блоге.
В принципе, вы не разрешаете асинхронность ASP.NET - вы просто скрываете синхронный код, привязанный к процессору, за фасадом async. Async
сам по себе идеально подходит для привязанного к I/O кода, поскольку он позволяет использовать CPU (потоки) с максимальной эффективностью (без блокировки для ввода-вывода), но когда у вас есть код, связанный с вычислением, вы все равно будете иметь использовать процессор в той же степени.
И принимая во внимание дополнительные накладные расходы от Task
и переключение контекста, вы получите еще более суровые результаты, чем простые методы контроллера синхронизации.
КАК СДЕЛАТЬ ИСТИННУЮ АСЫНЦУ:
GetNewsFeedItemsForUser
метод превращается в Async
.
[Route("user/{userId}/feeds/async")]
[HttpGet]
public async Task<IEnumerable<NewsFeedItem>> GetNewsFeedItemsForUserAsync(string userId)
{
return await _newsFeedService.GetNewsFeedItemsForUser(userId);
}
Для этого:
- Если это какой-то метод библиотеки, ищите его вариант
Async
(если их нет - неудача, вам придется искать какой-то конкурирующий аналог). - Если это ваш собственный метод, использующий файловую систему или базу данных, тогда используйте их асинхронные средства для создания асинхронного API для этого метода.