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а?

4 Solutions collect form web for “Is Task.Run считается плохой практикой в ​​веб-приложении ASP .NET MVC?”

Есть ли преимущество в производительности при использовании 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) как это фактически снизит вашу производительность.

  • Пример async / wait, который вызывает тупик
  • Перекачка сообщений StaTaskScheduler и STA
  • Параметры TaskCreationOptions.LongRunning и ThreadPool
  • Использует ли использование async / wait новый stream?
  • Ожидание нескольких задач с разными результатами
  • Метод общего назначения FromEvent
  • Лучшая практика для вызова ConfigureAwait для всего кода на стороне сервера
  • Текущий SynchronizationContext не может использоваться как TaskScheduler
  • Поймать исключение, вызванное асинхронным методом
  • Как я могу сообщить Moq о возврате задачи?
  • Как SynchronizationContext.Current основного streamа становится нулевым в приложении Windows Forms?
  • Interesting Posts

    Алгоритм для обнаружения пересечения двух прямоугольников?

    Как я могу заставить функциональные возможности Excel отменить / повторить работу более традиционным * для каждого окна * (а не для всего экземпляра Excel)?

    Функция триггера jquery, когда элемент находится в viewport

    Может ли расширение параметра встраиваться в Bash?

    Значение Autonumber последней вставленной строки – MS Access / VBA

    Не удалось инициализировать прокси – нет сеанса

    Удаление свойств и личной информации – пакетный режим или приложение

    Инструменты для проверки .lib-файлов?

    Альтернативы java.lang.reflect.Proxy для создания прокси абстрактных classов (а не интерфейсов)

    Как добавить параметры в WebRequest?

    Восстановить таблицу разделов, все еще присутствующую в запущенной системе

    Преобразование Json Array в обычный Java-массив

    Как увеличить память для Android Emulator? (INSTALL_FAILED_INSUFFICIENT_STORAGE)

    Ubuntu 9.04, AMD и nVidia: как определить причину блокировки?

    Как обмениваться компьютером через беспроводной маршрутизатор в Windows?

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