Ho lavorato a un articolo sui metodi dei controller asincroni in ASP.NET MVC ( link ) e penso che possa mancare il punto.
Considera questo metodo che ho scritto, che è molto simile a un esempio tratto dall'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);
}
Mentre capisco le cose, questo è il modo in cui le cose si svolgeranno in fase di runtime:
-
Verrà creato un thread ASP.NET per una richiesta HTTP in entrata.
-
Questo thread (presumibilmente avrà fatto un lavoro preliminare necessario) inserirà il mio metodo Index () sopra.
-
L'esecuzione raggiungerà la parola chiave "await" e darà il via a un processo di acquisizione dati su un altro thread.
-
Il thread "ASP.NET" originale tornerà al codice che ha chiamato il mio metodo handler, con un'istanza di classe Task come valore di ritorno.
-
Il codice infrastrutturale che ha chiamato il mio metodo handler continuerà a funzionare sul thread "ASP.NET" originale, fino a raggiungere un punto in cui è necessario utilizzare l'oggetto ActionResult effettivo (ad esempio per eseguire il rendering della pagina).
-
Il chiamante accederà quindi a questo oggetto usando il membro Task.Result, che lo farà (cioè il thread "ASP.NET") per attendere il thread creato implicitamente nel passaggio # 3 sopra.
Non vedo cosa comporti questo rispetto alla stessa cosa senza attendere / asincronizzare, tranne che per due cose che percepisco come insignificanti:
-
Il thread del chiamante e il thread di lavoro creati dall'attesa possono operare in parallelo per un certo periodo di tempo (la parte "fino a" del precedente # 5). La mia impressione è che il periodo di tempo sia piuttosto piccolo. Quando l'infrastruttura richiama un metodo di controllo, penso che in genere sia necessario l'effettivo ActionResult della chiamata del controller prima che possa fare molto (se mai) di più.
-
Esistono alcune nuove infrastrutture utili relative al timeout e all'annullamento delle operazioni con controller asincrono di lunga durata.
Lo scopo di aggiungere metodi di controller asincrono dovrebbe liberare quei thread di lavoro ASP.NET per rispondere effettivamente alle richieste HTTP. Questi thread sono una risorsa finita. Sfortunatamente, non vedo come il pattern suggerito nell'articolo serva effettivamente a conservare questi thread. E anche se lo fa, e in qualche modo scarica l'onere di gestire la richiesta su qualche thread non-ASP.NET, che cosa comporta? I thread che sono in grado di gestire una richiesta HTTP molto diversa dai thread in generale?