Должен ли я переносить медленные вызовы с помощью Task.Run?

У меня есть этот вызов ASP MVC, который является aync из-за асинхронного вызова, который он должен выполнить. Я заметил, что есть несколько медленных вызовов синхронизации (например, доступ к db). Для продолжения работы необходимо иметь все возвращенные данные.

Я думал об упаковке вызовов синхронизации с помощью Task.Run и ожидал их всех.

Есть ли смысл обернуть медленные вызовы синхронизации? Что делать, если были только вызовы синхронизации?

Ответ 1

Не используйте Task.Run для распараллеливания работы в серверном коде, если количество запросов клиентов, которые вы ожидаете использовать одновременно, действительно низкое. В противном случае вы можете ускорить обработку отдельного запроса, но вы повредите масштабируемость своего веб-приложения, когда есть много пользователей.

Ответ 2

Чтобы попытаться расширить @Noseratio, вращение нити для ускорения работы с синхронизацией очень тяжело.

Важно помнить, что использование Task.Run внутри ASP.NET чрезвычайно опасно, потому что среда выполнения не знает, как вы выполняете работу в очереди, и что IIS может время от времени пытаться перерабатывать ваше приложение, что будет вызывают непредсказуемую работу.

Если вы используете .NET Framework 4.5.2, есть решение через HostingEnvironment.QueueBackgroundWorkItem. Подробнее об этом можно узнать в Fire and Forget on ASP.NET. Если нет, прочитайте Returning Early from ASP.NET Requests для пользовательской реализации. Обе эти превосходные статьи принадлежат @StephanCleary

Ответ 3

Если задачи независимы (не зависят от данных от других задач) и могут выполняться независимо, то да, непременно выполняйте их асинхронно. Если это Entity Framework, а версия 6, то она предлагает методы Async для вызова, и вам не нужно их обертывать в Task.Run.

Даже если задачи не являются независимыми, вы все равно сможете их упорядочить, чтобы сделать их более эффективными при выполнении.

Использовать ли Task.Run, однако, является важным отличием. Task.Run будет использовать поток ThreadPool, который, если он сделает что-то синхронное, заблокирует и, следовательно, уменьшит количество атак ThreadPool, доступных вашему приложению. Если у вас много пользователей, и вы выполняете множество задач, это может быть проблемой.

Попробуйте найти async api, а не использовать Task.Run.