Is Task.Run считается плохой практикой в ​​веб-приложении ASP .NET MVC?

Задний план

В настоящее время мы разрабатываем веб-приложение, основанное на ASP.NET MVC 5, Angular.JS 1.4, Web API 2 и Entity Framework 6. По соображениям масштабируемости маневренность веб-приложений зависит от шаблона async / await. Для нашего домена требуются некоторые интенсивные вычисления, которые могут занимать несколько секунд ( См. сообщение Стивена Клири в блоге ), они использовали ConfigureAwait (false).

пример

public async Task CalculateAsync(double param1, double param2) { // CalculateSync is synchronous and cpu-intensive ( this.CalculateSync(param1, param2))).ConfigureAwait(false); } 

Вопросов

  • Есть ли преимущество в производительности при использовании Task.Run в async Web API Controller для операций с привязкой к процессору?
  • Действительно ли ConfigureAwait (false) действительно предотвращает создание дополнительного streamа?

Есть ли преимущество в производительности при использовании Task.Run в async Web API Controller для операций с привязкой к процессору?

Нуль. Никто. Фактически, вы препятствуете выполнению, создавая новый stream. В контексте веб-приложения нереста streamа – это не то же самое, что работает в «фоновом режиме». Это связано с характером веб-запроса. Когда есть входящий запрос, stream берется из пула для обслуживания запроса. Использование async позволяет возвращать stream до конца запроса тогда и только тогда, когда stream находится в состоянии ожидания, то есть в режиме ожидания. Создавая stream для работы, эффективно простаивает основной stream, позволяя ему возвращаться в пул, но у вас все еще есть активный stream. Возврат исходной нити в пул ничего не делает в этот момент. Затем, когда новый stream завершит свою работу, вы должны запросить основной stream из пула и, наконец, вернуть ответ. Ответ не может быть возвращен до завершения всей работы, поэтому, если вы используете 1 нить или сто, асинхронную или синхронизацию, ответ не может быть возвращен, пока все не закончится. Поэтому использование дополнительных streamов ничего не делает, кроме добавления служебных данных.

Действительно ли ConfigureAwait (false) действительно предотвращает создание дополнительного streamа?

Нет, или более правильно, дело не в этом. ConfigureAwait – это всего лишь подсказка по оптимизации, и только определяет, поддерживается ли исходный контекст между streamовыми переходами. Длительный и короткий, он не имеет ничего общего с созданием streamа и, по крайней мере, в контексте приложения ASP.NET, имеет незначительное влияние на производительность в любом случае.

Есть ли преимущество в производительности при использовании Task.Run в async Web API Controller для операций с привязкой к процессору?

Нет. И неважно, связан ли он с процессором или нет.

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

Это полезно в приложениях пользовательского интерфейса, где stream пользовательского интерфейса представляет собой отдельный отдельный stream.

Действительно ли ConfigureAwait (false) действительно предотвращает создание дополнительного streamа?

Это не влияет на создание streamов так или иначе. Все, что он делает, настраивает, будет ли возобновлено захваченное SynchronizationContext или нет.

Есть ли преимущество в производительности при использовании Task.Run в async Web API Controller для операций с привязкой к процессору?

Подумайте о том, что на самом деле происходит – Task.Run() создает задачу в пуле streamов, и ваш оператор await освободит stream (я также предполагаю, что все методы в стеке также ждут). Теперь ваш stream возвращается в пул, и он может забрать ту же задачу! В этом случае, очевидно, нет увеличения производительности. На самом деле это удар производительности. Но если stream подхватит еще одну задачу (это, вероятно, произойдет), другой stream должен будет забрать задачу CalculateSync() и продолжить с того места, где бывшая остановилась. Было бы разумнее позволить исходному streamу выполнять CalculateSync() в первую очередь, без участия Задачи, и пусть другой stream будет иметь другие задачи в очереди.

Действительно ли ConfigureAwait (false) действительно предотвращает создание дополнительного streamа?

Не за что. Он просто указывает, что продолжение не должно выполняться в контексте вызывающего абонента.

Есть еще одна вещь, которую вам нужно рассмотреть. Когда вы сказали, что ваш api делает задачу с интенсивным процессором, асинхронно / ждут помощи, чтобы запустить процесс в другом streamе и освободить пул приложений для другого запроса. Значит, ваш веб-api может обрабатывать большее количество запросов в секунду, если вы правильно используете async / await.

В вашем случае выглядят следующим образом. this.CalculateSync(param1, param2) является неасинхронным методом, поэтому для асинхронного вызова вы должны использовать Task.Run.

Я рекомендую удалить .ConfigureAwait(false) как это фактически снизит вашу производительность.

  • Асинхронно ждать Task , чтобы завершить таймаут
  • Использование async / ожидание нескольких задач
  • Как я могу сообщить Moq о возврате задачи?
  • В чем разница между Task.Start / Wait и Async / Await?
  • Как отменить задачу в ожидании?
  • Как использовать API-интерфейсы и шаблоны async / await без streamов для ASP.NET Web API?
  • AspNetSynchronizationContext и ожидает продолжения в ASP.NET
  • Параметры TaskCreationOptions.LongRunning и ThreadPool
  • Что касается использования Task.Start (), Task.Run () и Task.Factory.StartNew ()
  • Глобальный обработчик исключений TAP
  • Самый простой способ сделать огонь и забыть метод в c # 4.0
  • Interesting Posts

    Нестационарный член как аргумент по умолчанию для функции нестатического члена

    Диалоговое окно Android Alert с одной, двумя и тремя кнопками

    Диагностика проблем с внешним жестким диском USB

    Могу ли я установить дополнительный языковой пакет на Microsoft Surface?

    Если мы не будем использовать обои на рабочем столе, это увеличит производительность окон?

    Использовать имя classа в качестве корневого ключа для сериализации JSON Jackson

    firebase database против плоских файлов

    Переадресация по умолчанию для Error 404

    Интернет через Ethernet: DNS работает, ping не работает (Windows работает, Linux не работает)

    Производительность bcp / BULK INSERT по сравнению с табличными параметрами

    Как получить информацию о битрейме с видео YouTube?

    Есть ли способ настроить командную строку командной строки Windows?

    Чтение logcat программно в приложении

    Как добавить дополнительный исходный каталог для maven для компиляции и включения в сборку jar?

    В Windows 7, как изменить настройки прокси-сервера из командной строки?

    Давайте будем гением компьютера.