Controller asincroni in ASP.NET MVC: Vantaggi reali / Come realizzato?


12

Ho lavorato su un articolo sui metodi del controller asincrono in ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx ) e penso Forse mi manca il punto.

Considera questo metodo che ho scritto, che è molto simile a un esempio dell'articolo:

[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);
}

Come capisco le cose, questo è come le cose si svolgeranno in fase di esecuzione:

  1. Verrà creato un thread ASP.NET per una richiesta HTTP in entrata.

  2. Questo thread (presumibilmente fatto qualche lavoro preliminare necessario) entrerà nel mio metodo Index () sopra.

  3. L'esecuzione raggiungerà la parola chiave "wait" e avvierà un processo di acquisizione dati su un altro thread.

  4. Il thread "ASP.NET" originale tornerà al codice che chiamava il mio metodo handler, con un'istanza della classe Task come valore di ritorno.

  5. Il codice infrastrutturale che ha chiamato il mio metodo handler continuerà a funzionare sul thread originale "ASP.NET", fino a quando non raggiunge un punto in cui deve utilizzare l'oggetto ActionResult effettivo (ad esempio per eseguire il rendering della pagina).

  6. Il chiamante accederà quindi a questo oggetto utilizzando il membro Task.Result, che farà sì che esso (ovvero il thread "ASP.NET") attenda il thread creato implicitamente nel passaggio 3 sopra.

Non vedo ciò che questo compie rispetto alla stessa cosa senza attesa / asincrono, ad eccezione di due cose che percepisco insignificanti:

  • Il thread del chiamante e il thread di lavoro creati da waitit possono funzionare in parallelo per un certo periodo di tempo (la parte "fino a" del numero 5 sopra). La mia idea è che il periodo di tempo sia piuttosto piccolo. Quando l'infrastruttura chiama un metodo controller, penso che in genere abbia bisogno dell'effettivo ActionResult della chiamata controller prima che possa fare molto (se non altro) di più.

  • Esistono alcune nuove utili infrastrutture relative al timeout e alla cancellazione di operazioni di controller asincrone di lunga durata.

Lo scopo di aggiungere metodi del controller asincrono è quello di liberare quei thread di lavoro ASP.NET per rispondere effettivamente alle richieste HTTP. Questi thread sono una risorsa limitata. Sfortunatamente, non vedo come lo schema suggerito nell'articolo serva effettivamente a conservare questi thread. E anche se lo fa, e in qualche modo scarica l'onere della gestione della richiesta su un thread non-ASP.NET, cosa compie questo? I thread che sono in grado di gestire una richiesta HTTP sono molto diversi dai thread in generale?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Non necessariamente. asyncnon richiede un altro thread ... È una continuazione. Può essere realizzato riordinando le istruzioni sullo stesso thread.
Robert Harvey,


"L'esecuzione raggiungerà la parola chiave wait e darà il via a un processo di acquisizione dati su un altro thread." hai questo al contrario: l'attesa è quando torna. Prova a dividerlo in modo da salvare il risultato da GetAllAsync () in una variabile e attenderlo invece e vedere se diventa più chiaro.
Esben Skov Pedersen,

Risposte:


9

ASP.Net che non utilizza Task Parallel Library (TPL) è limitato nel numero di richieste che può gestire contemporaneamente dal numero di thread in un pool di thread. ASP.Net che utilizza TPL è limitato dalla CPU / memoria / IO delle richieste di gestione della macchina.

La Task Parallel Library (TPL) non consuma discussioni nel modo in cui sembra che pensi. Le attività non sono thread, sono un wrapper per alcune unità di calcolo. L'utilità di pianificazione è responsabile dell'esecuzione di ogni attività su qualsiasi thread non occupato. In fase di esecuzione, l'attesa di un'attività non blocca il thread, ma semplicemente parcheggia lo stato di esecuzione in modo che possa procedere in un secondo momento.

Normalmente, una singola richiesta HTTP viene gestita da un singolo thread, rimuovendo completamente quel thread dal pool fino a quando non viene restituita una risposta. Con il TPL, non sei vincolato da questo vincolo. Qualsiasi richiesta che arriva avvia una continuazione con ogni unità di calcolo richiesta per calcolare una risposta in grado di eseguire su qualsiasi thread nel pool. Con questo modello, è possibile gestire molte più richieste simultanee rispetto a ASP.Net standard.


Quindi, quando viene restituito il thread ASP.NET al pool? Quando viene premuta la parola chiave "wait"?
user1172763

async / await + TPL consente al compilatore di dividere il codice in unità computazionali indipendenti che vengono eseguite dall'utilità di pianificazione. Un thread viene concettualmente restituito al pool quando l'utilità di pianificazione non ha più attività che possono essere eseguite e il thread termina il lavoro assegnato.
mortalapeman

Questa è concettualmente corretta e probabilmente una risposta utile ... tuttavia la realtà è solo un po 'più complicata a causa dell'agilità del thread .
John Wu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.