Яка перевага використання async з MVC5?


120

Яка різниця між:

public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = IdentityManager.Authentication.CheckPasswordAndSignIn(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

і:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = await IdentityManager.Authentication.CheckPasswordAndSignInAsync(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

Я бачу, що в коді MVC тепер є асинхронність, але в чому різниця. Чи дає один набагато кращі показники, ніж інший? Чи легше налагоджувати проблеми однією, ніж іншою? Чи потрібно вносити зміни до інших контролерів для моєї програми, щоб додати Async?


У переважній більшості ситуацій немає серйозної користі для використання async у MVC, проте є багато негативів
Кріс Марісіч

1
@ChrisMarisic - Одне з найсерйозніших: ви не можете використовувати ReaderWriterLock або будь-який з інших примітивів для синхронізації (за винятком Semaphore).
Щоквартально

Відповіді:


170

Дії асинхронізації корисні лише тоді, коли ви виконуєте операції, пов'язані з входом / виводом, такі як виклики віддаленого сервера. Перевага виклику async полягає в тому, що під час операції вводу / виводу жодна робоча нитка ASP.NET не використовується. Ось ось як працює перший приклад:

  1. Коли запит потрапляє на дію, ASP.NET бере нитку з пулу потоків і починає її виконувати.
  2. IdentityManager.Authentication.CheckPasswordAndSignInМетод викликається. Це виклик блокування -> під час усього виклику піддаються робочій нитці.

А ось як працює другий дзвінок:

  1. Коли запит потрапляє на дію, ASP.NET бере нитку з пулу потоків і починає її виконувати.
  2. IdentityManager.Authentication.CheckPasswordAndSignInAsyncНазивається , який негайно повертається. Реєструється порт завершення вводу / виводу, і робоча нитка ASP.NET випускається в пул потоків.
  3. Пізніше, коли операція завершується, порту завершення вводу / виводу сигналізується, інший потік витягується з пулу потоків, щоб закінчити повернення подання.

Як ви бачите у другому випадку, потоки робочих ASP.NET використовуються лише короткий проміжок часу. Це означає, що в пулі є більше потоків для обслуговування інших запитів.

Отже, щоб зробити висновок, використовуйте дії async лише тоді, коли у вас є справжній API async. Якщо ви робите блокуючий виклик всередині дії асинхронізації, ви знищуєте всю користь від цього.


Як щодо синхронізації контексту. Невже це не буде таким накладним, що ви взагалі не хочете використовувати дії асинхронізації? "Накладні витрати асинхронного методу, які фактично виконують асинхронно, повністю залежать від того, чи потрібно йому перемикати потоки, використовуючи SynchronizationContext.Post. Якщо це так, накладні витрати переважають через потоковий комутатор, який він виконує під час відновлення. Це означає, що поточна синхронізаціяContext робить велика різниця ». (Async in C # 5.0, 2012, Alex Davies)
annemartijn

1
@Darin Чому так важливо випустити основну нитку? Чи обмежена нитка?
Омтехгуй

1
@Omtechguy кращим рішенням є переміщення не ASP.NET запитів на CDN. Простий CDN - це лише використання піддомену та окремий пул додатків для фізичних файлів, таких як ваш JavaScript та зображення. Крім того, ви можете використовувати для файлів NgineX / Lighttpd / Apache, або ви можете скористатись стороннім сервісом, таким як Akamai (король для CDN, але найдорожчий)
Chris Marisic

Я все ще розгублений. Коли CheckPasswordAndSignInAsyncвикликається, ASP.NET бере інший потік з пулу потоків і починає його виконувати, чи не так? Якщо ні, то де checking password procedureвиконується?
КевінБуї

2

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

Якщо це якесь нове завдання, яке буде породжене, чи ні, і якщо його слід чекати чи ні. Завжди думайте про ці 70 мс, що приблизно. макс. час, який повинен зайняти будь-який виклик методу. Якщо його довше, то ваш інтерфейс, швидше за все, не буде відчувати дуже чуйності.


0

У веб-додатках, які бачать велику кількість одночасних запитів під час запуску або мають бурхливе навантаження (де паралельність зростає раптово), введення цих викликів веб-служб асинхронними підвищить чутливість вашої програми. Асинхронний запит обробляє стільки ж часу, скільки і синхронний запит. Наприклад, якщо запит здійснює дзвінок веб-служби, для виконання якого потрібні дві секунди, запит займає дві секунди, виконується він синхронно чи асинхронно. Однак під час асинхронного дзвінка потік не блокується відповідати на інші запити, поки він чекає завершення першого запиту. Тому асинхронні запити запобігають черзі запитів та росту пулу потоків, коли існує багато паралельних запитів, які викликають тривалі операції.


Якщо ваш додаток aspnet значною мірою складається з дзвінків на інші веб-сервери, ви багато в чому поводите себе як "шлюз" / "проксі", і для цього асинхрон корисний.
Кріс Марісіч
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.