Per l'apprendimento più veloce ..
Comprendere il flusso di esecuzione del metodo (con un diagramma): 3 minuti
Domanda introspezione (apprendimento): 1 min
Passa rapidamente attraverso la sintassi dello zucchero: 5 minuti
Condividi la confusione di uno sviluppatore: 5 minuti
Problema: modifica rapida di un'implementazione nel mondo reale del codice normale in codice asincrono: 2 minuti
Dove andare dopo?
Comprendere il flusso di esecuzione del metodo (con un diagramma): 3 minuti
In questa immagine, concentrati solo sul numero 6 (niente di più)
Al passaggio n. 6: l'esecuzione si è fermata qui perché è rimasta senza lavoro. Per continuare ha bisogno di un risultato da getStringTask (tipo di funzione). Pertanto, utilizza un await
operatore per sospendere i suoi progressi e restituire il controllo (rendimento) al chiamante (di questo metodo in cui ci troviamo). La chiamata effettiva a getStringTask è stata effettuata in precedenza nel numero 2. Al n. 2 è stata promessa di restituire un risultato di stringa. Ma quando restituirà il risultato? Dovremmo (# 1: AccessTheWebAsync) effettuare nuovamente una seconda chiamata? Chi ottiene il risultato, # 2 (dichiarazione di chiamata) o # 6 (in attesa di dichiarazione)
Anche il chiamante esterno di AccessTheWebAsync () è in attesa ora. Quindi il chiamante in attesa di AccessTheWebAsync e AccessTheWebAsync sta aspettando GetStringAsync al momento. La cosa interessante è che AccessTheWebAsync ha lavorato un po 'prima di aspettare (# 4) forse per risparmiare tempo dall'attesa. La stessa libertà di multitasking è disponibile anche per il chiamante esterno (e per tutti i chiamanti della catena) e questo è il più grande vantaggio di questa cosa "asincrona"! Ti senti sincrono ... o normale ma non lo è.
Ricorda, il metodo è già stato restituito (n. 2), non può più essere restituito (nessuna seconda volta). Quindi come farà il chiamante a saperlo? Si tratta di Compiti! L'attività è stata passata. L'attività era in attesa (non metodo, non valore). Il valore verrà impostato in Attività. Lo stato dell'attività verrà impostato per il completamento. Il chiamante monitora solo l'attività (n. 6). Quindi 6 # è la risposta a dove / chi ottiene il risultato. Ulteriori letture per più tardi qui .
Domanda introspezione per motivi di apprendimento: 1 min
Modifichiamo un po 'la domanda:
Come e quando usare e ? async
await
Tasks
Perché l'apprendimento Task
copre automaticamente gli altri due (e risponde alla tua domanda)
Passa rapidamente attraverso la sintassi dello zucchero: 5 minuti
Prima della conversione (metodo originale)
internal static int Method(int arg0, int arg1)
{
int result = arg0 + arg1;
IO(); // Do some long running IO.
return result;
}
un metodo Task-ified per chiamare il metodo sopra
internal static Task<int> MethodTask(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
Abbiamo già detto in attesa o asincrono? No. Chiama il metodo sopra e otterrai un'attività che puoi monitorare. Sai già cosa restituisce l'attività .. un numero intero.
Chiamare un'attività è leggermente complicato ed è allora che iniziano a comparire le parole chiave. Chiamiamo MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
Stesso codice sopra aggiunto come immagine qui sotto:
- Stiamo "aspettando" il completamento del compito. Quindi il
await
- Poiché usiamo waitit, dobbiamo usare
async
(sintassi obbligatoria)
- MethodAsync con
Async
come prefisso (standard di codifica)
await
è facile da capire ma i restanti due ( async
, Async
) potrebbero non essere :). Beh, dovrebbe avere molto più senso per il compilatore, ma leggi più avanti qui
Quindi ci sono 2 parti.
- Crea 'Task'
- Crea zucchero sintattico per chiamare l'attività (
await+async
)
Ricorda, abbiamo avuto un chiamante esterno per AccessTheWebAsync () e neanche quel chiamante è risparmiato ... cioè ha bisogno anche dello stesso await+async
. E la catena continua. Ma ci sarà sempre una Task
a un'estremità.
Tutto bene, ma uno sviluppatore è stato sorpreso di vedere mancare il numero 1 (attività) ...
Condividi la confusione di uno sviluppatore: 5 minuti
Uno sviluppatore ha fatto un errore di non implementazione Task
ma funziona ancora! Cerca di capire la domanda e solo la risposta accettata fornita qui . Spero che tu abbia letto e compreso appieno. Il riassunto è che potremmo non vedere / implementare "Task" ma è implementato da qualche parte in una classe genitore. Allo stesso modo, nel nostro esempio, chiamare un già costruito MethodAsync()
è molto più semplice che implementare quel metodo con un Task
( MethodTask()
) noi stessi. La maggior parte degli sviluppatori ha difficoltà a orientarsi Tasks
mentre converte un codice in uno asincrono.
Suggerimento: prova a trovare un'implementazione Async esistente (come MethodAsync
o ToListAsync
) per esternalizzare la difficoltà. Quindi dobbiamo solo occuparci di Async e attendere (che è facile e abbastanza simile al normale codice)
Problema: modifica rapida di un'implementazione nel mondo reale del codice normale in operazione asincrona: 2 minuti
La riga di codice mostrata di seguito in Livello dati ha iniziato a rompersi (molti punti). Perché abbiamo aggiornato parte del nostro codice da .Net framework 4.2. * A .Net core. Abbiamo dovuto risolvere questo problema in 1 ora in tutta l'applicazione!
var myContract = query.Where(c => c.ContractID == _contractID).First();
vai tranquillo!
- Abbiamo installato il pacchetto nuget EntityFramework perché ha QueryableExtensions. O in altre parole esegue l'implementazione Async (attività), in modo da poter sopravvivere con codice semplice
Async
e await
in codice.
- namespace = Microsoft.EntityFrameworkCore
la linea del codice chiamante è stata modificata in questo modo
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
Firma del metodo modificata da
Contract GetContract(int contractnumber)
per
async Task<Contract> GetContractAsync(int contractnumber)
Anche il metodo di chiamata è stato interessato: è GetContractAsync(123456);
stato chiamato comeGetContractAsync(123456).Result;
L'abbiamo cambiato ovunque in 30 minuti!
Ma l'architetto ci ha detto di non usare la libreria EntityFramework solo per questo! oops! Dramma! Quindi abbiamo realizzato un'implementazione Task personalizzata (yuk). Che tu sai come. Ancora facile! ..still yuk ..
Dove andare dopo?
C'è un meraviglioso video rapido che potremmo guardare sulla conversione di chiamate sincrone in asincrone in ASP.Net Core , forse è probabilmente la direzione in cui andremmo dopo aver letto questo.