Асинхронні контролери в ASP.NET MVC: реальні переваги / як досягти?


12

Я працював над статтею про асинхронні методи контролера в ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-action-in-aspnet-mvc-4.aspx ) і думаю Можливо, я пропускаю суть.

Розглянемо цей метод, який я написав, який дуже схожий на приклад зі статті:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

Як я розумію, саме так розгортаються речі під час виконання:

  1. Для вхідного запиту HTTP буде створений потік ASP.NET.

  2. Цей потік (імовірно, виконавши якусь необхідну попередню роботу) введе мій метод Index () вище.

  3. Виконання досягне ключового слова "очікувати" і розпочнеть процес збору даних на іншому потоці.

  4. Оригінальний потік "ASP.NET" повернеться до коду, який називається моїм методом обробника, із екземпляром класу Task як поверненим значенням.

  5. Інфраструктурний код, який викликав метод мого обробника, буде продовжувати працювати на оригінальній потоці "ASP.NET" до тих пір, поки не досягне точки, коли йому потрібно використовувати фактичний об'єкт ActionResult (наприклад, для візуалізації сторінки).

  6. Потім абонент отримає доступ до цього об’єкта за допомогою члена Task.Result, що змусить його (тобто потоку "ASP.NET") чекати потоку, створеного неявно на кроці №3 вище.

Я не бачу, що це досягає порівняно з тим самим, що не чекає / асинхронізує, за винятком двох речей, які я сприймаю як дрібницю:

  • Потік виклику та робочий потік, створений програмою await, можуть працювати паралельно протягом певного періоду часу (частина "до" №5 вище). Моя думка, що проміжок часу досить малий. Коли інфраструктура викликає метод контролера, я думаю, що він, як правило, потребує фактичного ActionResult виклику контролера, перш ніж він може зробити набагато більше (якщо що-небудь) більше.

  • Існує нова корисна нова інфраструктура, пов’язана з тимчасовим очікуванням та скасуванням тривалих операцій асинхронного контролера.

Мета додавання методів контролера async - це нібито звільнити ці робочі потоки ASP.NET, щоб реально відповідати на HTTP-запити. Ці нитки є кінцевим ресурсом. На жаль, я не бачу, як шаблон, запропонований у статті, насправді служить для збереження цих ниток. І навіть якщо це відбувається, і якимось чином вивантажує тягар обробки запиту на якусь нитку, яка не є ASP.NET, що це досягає? Чи потоки, які, здається, здатні обробляти HTTP-запит, сильно відрізняються від потоків взагалі?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Не обов'язково. asyncне вимагає іншої нитки ... Це продовження. Це можна досягти шляхом переупорядкування інструкцій на одній нитці.
Роберт Харві


"Виконання досягне ключового слова, що очікує, і розпочне процес збору даних в іншому потоці." Ви отримали це назад: очікування, коли воно повернеться. Спробуйте розділити його, щоб ви зберегли результат від GetAllAsync () у змінній і чекаєте, що замість цього і побачите, чи стане він більш зрозумілим.
Есбен Сков Педерсен

Відповіді:


9

ASP.Net, який не використовує бібліотеку паралельних завдань (TPL), обмежений у кількості запитів, з якими вона може одночасно оброблятись кількістю потоків у пулі потоків. ASP.Net, що використовує TPL, обмежений процесором / пам'яттю / IO запитів на обробку машини.

Бібліотека паралельних завдань (TPL) не споживає потоки так, як вам здається, це робить. Завдання - це не нитки, вони - обгортка навколо якоїсь одиниці обчислення. Планувальник завдань відповідає за виконання кожного завдання на будь-якому потоці, який не зайнятий. Під час виконання очікування завдання не блокує потік, воно просто паркує стан виконання, щоб воно могло продовжуватись у більш пізній час.

Зазвичай один запит HTTP обробляється одним потоком, повністю видаляючи цей потік з пулу, поки відповідь не буде повернута. З TPL ви не обмежуєтесь цим обмеженням. Будь-який запит, що надходить, починає продовження з кожною одиницею обчислення, необхідною для обчислення відповіді, здатної виконати на будь-якому потоці в пулі. За допомогою цієї моделі ви можете обробити набагато більше одночасних запитів, ніж зі стандартною ASP.Net.


Отже, коли потік ASP.NET повертається до пулу? Коли буде натиснуто ключове слово "очікувати"?
користувач1172763

async / await + TPL дозволяють компілятору розділити ваш код на незалежні обчислювальні одиниці, які виконуються планувальником завдань. Потік концептуально повертається в пул, коли у планувальника завдань більше немає завдань, які можна виконати, і потік закінчує задану йому роботу.
mortalapeman

Це концептуально правильна і, ймовірно, корисна відповідь ... однак реальність просто складніше через спритність потоку .
Джон Ву
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.