Quando dovrei usare i controller asincroni in ASP.NET MVC?

Quando dovrei usare i controller asincroni in ASP.NET MVC?

Potresti trovare utile il mio articolo MSDN sull'argomento; Ho preso molto spazio in quell'articolo che descrive quando dovresti usa async su ASP.NET, non solo come per utilizzare async su ASP.NET.

Innanzitutto, comprendi quel async /await si tratta di liberare i thread . Nelle applicazioni GUI, si tratta principalmente di liberare il thread della GUI quindi l'esperienza dell'utente è migliore. Nelle applicazioni server (incluso ASP.NET MVC), si tratta principalmente di liberare il thread della richiesta in modo che il server possa ridimensionarsi.

In particolare, non:

  • Rendi le tue richieste individuali completate più velocemente. In effetti, si completeranno (solo un pochino) più lentamente.
  • Torna al chiamante/browser quando premi un await . await "rende" solo al pool di thread ASP.NET, non al browser.

Direi che è bene usarlo ovunque tu stia facendo I/O. Potrebbe non essere necessariamente utile , però (vedi sotto).

Tuttavia, è cattivo per usarlo per i metodi legati alla CPU. A volte gli sviluppatori pensano di poter ottenere i vantaggi di async semplicemente chiamando Task.Run nei loro controller, e questa è un'idea orribile. Perché quel codice finisce per liberare il thread di richiesta occupando un altro thread, quindi non c'è alcun vantaggio (e in effetti, stanno subendo la penalità di cambi di thread aggiuntivi)!

Potresti usare qualsiasi metodo disponibile tu abbia a disposizione. In questo momento la maggior parte dei principali giocatori supporta async , ma ce ne sono alcuni che non lo fanno. Se il tuo ORM non supporta async , quindi non provare a racchiuderlo in Task.Run o qualcosa del genere (vedi sopra).

Nota che ho detto "tu potresti use". Se stai parlando di ASP.NET MVC con un singolo backend di database, allora (quasi certamente) non otterrai alcun vantaggio di scalabilità da async . Questo perché IIS può gestire molte più richieste simultanee rispetto a una singola istanza di SQL Server (o altri classici RDBMS). Tuttavia, se il tuo back-end è più moderno (un cluster di server SQL, Azure SQL, NoSQL e così via) e il tuo back-end può essere ridimensionato e il tuo collo di bottiglia della scalabilità è IIS, allora puoi ottenere un vantaggio di scalabilità da async .

Quanti ne vuoi. Tuttavia, si noti che molti ORM hanno una regola di un'operazione per connessione. In particolare, EF consente una sola operazione per DbContext; questo è vero sia che l'operazione sia sincrona o asincrona.

Inoltre, tieni di nuovo a mente la scalabilità del tuo back-end. Se stai colpendo una singola istanza di SQL Server e il tuo IIS è già in grado di mantenere SQLServer a piena capacità, raddoppiare o triplicare la pressione su SQLServer non ti aiuterà affatto.


Azione asincrona I metodi sono utili quando un'azione deve eseguire diverse operazioni indipendenti di lunga durata.

Le mie chiamate al database dovrebbero essere asincrone?

Il pool di thread IIS può spesso gestire molte più richieste di blocco simultanee rispetto a un server di database. Se il database è il collo di bottiglia, le chiamate asincrone non accelereranno la risposta del database. Senza un meccanismo di limitazione, l'invio efficiente di più lavoro a un server di database sovraccaricato utilizzando chiamate asincrone trasferisce semplicemente una parte maggiore del carico sul database. Se il tuo DB è il collo di bottiglia, le chiamate asincrone non saranno la bacchetta magica.

dovresti dai un'occhiata a 1 e 2 riferimenti

Derivato dai commenti di @PanagiotisKanavos:


Come al solito in programmazione, dipende . C'è sempre un compromesso quando si percorre un certo percorso.

async-await brilla in luoghi in cui sai che riceverai richieste simultanee al tuo servizio e desideri essere in grado di scalare bene. Come funziona async-await aiuto con il ridimensionamento? Nel fatto che quando invochi un IO asincrono, chiama in modo sincrono , ad esempio una chiamata di rete o un impatto sul database, il thread corrente responsabile dell'esecuzione viene bloccato in attesa del completamento della richiesta. Quando usi async-await , consenti al framework di creare una macchina a stati per te che si assicura che dopo il completamento della chiamata IO, il tuo metodo continui a essere eseguito da dove era stato interrotto.

Una cosa da notare è che questa macchina a stati ha un leggero sovraccarico. Rendere un metodo asincrono non lo rende più veloce , e questo è un fattore importante da comprendere e un'idea sbagliata che molte persone hanno.

Un'altra cosa da tenere in considerazione quando si utilizza async-await è il fatto che è completamente asincrono , il che significa che vedrai l'async penetrare nell'intero stack di chiamate, dall'alto verso il basso. Ciò significa che se desideri esporre API sincrone, ti ritroverai spesso a duplicare una certa quantità di codice, poiché async e sincronizzazione non si combinano molto bene.

Se scegli di utilizzare le chiamate IO asincrone, allora sì, async-await sarà una buona scelta, poiché sempre più moderni provider di database espongono il metodo asincrono implementando il TAP (Task Asynchronous Pattern).

Quanti ne vuoi, purché tu segua le regole stabilite dal tuo fornitore di database. Non c'è limite alla quantità di chiamate asincrone che puoi effettuare. Se hai query indipendenti l'una dall'altra e che possono essere eseguite contemporaneamente, puoi creare una nuova attività per ciascuna e utilizzare await Task.WhenAll attendere il completamento di entrambi.