2012-09-19 15 views
5

Sto seguendo il await tutorial su MSDN, e sto cercando di capire la differenza tra l'utilizzo await come dichiarazione rispetto all'utilizzo await come espressione. Tutta questa cosa asincrona mi sta piegando la mente e non riesco a trovare esempi per questo caso particolare.attendono dichiarazione vs. espressione

Fondamentalmente, volevo vedere come usare più await s in modo asincrono, il che significa che non voglio dover aspettare che il primo si completi prima che inizi il secondo. Questo, per me, sconfigge lo scopo di asincronia per cominciare:

private async void button1_Click(object sender, EventArgs e) 
{ 
    // Using await as an expression 
    string result_a = await WaitAsynchronouslyAsync(); 
    string result_b = await WaitAsynchronouslyAsync(); 

    // This takes six seconds to appear 
    textBox1.Text = result_a + Environment.NewLine; 
    textBox1.Text += result_b; 
} 

public async Task<string> WaitAsynchronouslyAsync() 
{ 
    await Task.Delay(3000); 
    return "Finished"; 
} 

Tuttavia, con un sottile cambiamento ci vogliono solo 3 secondi totali per la s due "Finito" a comparire, che è quello che vorrei - i due await s in esecuzione veramente in modo asincrono:

private async void button1_Click(object sender, EventArgs e) 
{ 
    var a = WaitAsynchronouslyAsync(); 
    var b = WaitAsynchronouslyAsync(); 

    // Using await as a statement 
    await a; 
    await b; 

    // This takes three seconds to appear 
    textBox1.Text = a.Result + Environment.NewLine; 
    textBox1.Text += b.Result; 
} 

la mia domanda è, perché queste comportano in modo diverso? Che punto sottile mi manca qui?

risposta

11

In primo luogo, è necessario distinguere tra parallelismo e asincronia. Nel primo caso, potrebbe tranquillamente valere la pena eseguire le operazioni in modo sincrono (e infatti la seconda operazione può dipendere dai risultati del primo) per liberare il thread dell'interfaccia utente ecc.

Ma come per il motivo per cui si comportano in modo diverso - await è solo un'espressione. È il tipo di espressione che può apparire come una dichiarazione, ma si comporterà allo stesso modo, proprio come chiamare un metodo che restituisce una stringa, ma ignorando il valore restituito. Puoi vedere ciò cambiando il tuo primo codice in:

// Still takes 6 seconds... 
var a = WaitAsynchronouslyAsync(); 
await a; 

var b = WaitAsynchronouslyAsync(); 
await b; 

Ci vorranno ancora 6 secondi. Il punto è che stai iniziando la seconda operazione asincrona dopo il che hai aspettato per il primo a finire. Nel secondo esempio, entrambe le operazioni asincrone si verificano contemporaneamente.

si può ancora fare che e assegnare il valore di una variabile, basta ricordare i awaitables:

// This will only take 3 seconds 
var a = WaitAsynchronouslyAsync(); 
var b = WaitAsynchronouslyAsync(); 
string result_a = await a; 
string result_b = await b; 

Quindi, in pratica, la differenza non è a che fare con dichiarazione/espressione - è fare con se la sequenza è start/await/start/await o start/start/await/await.

+0

l'ultima modifica mi ha fatto capire, grazie - la sequenza è il problema. Avrei dovuto capire che sono entrambe espressioni. –

4

In entrambe le situazioni la parola chiave await introduce l'asincronia. La ragione per cui stai vedendo la differenza è che nel caso in cui tu avvii entrambi i compiti in sequenza, dove nel caso 2 li fai correre in parallelo.

Forse uno spiegazione passo passo di entrambe le situazioni cancella le cose

string result_a = await WaitAsynchronouslyAsync(); 
string result_b = await WaitAsynchronouslyAsync(); 

Quello che succede qui è:

  • un compito (a) viene avviato
  • compito una si è in attesa (controllo viene restituito al chiamante)
  • quando il task a termina dopo 3 secondi, il metodo riprende; compito (b) viene avviato
  • compito b è atteso (controllo viene restituito al chiamante)
  • quando compito b è finito dopo ulteriori 3 secondi, il testo viene visualizzato

Nel secondo caso:

viene avviato
var a = WaitAsynchronouslyAsync();  
var b = WaitAsynchronouslyAsync();  
await a;  
await b;  
  • compito (a)
  • compito (b) si avvia
  • compito (a) è 'aw aited '(cioè, il controllo viene restituito al chiamante)
  • quando l'attività (a) è terminata dopo 3 secondi, l'attività (b) è attesa
  • poiché l'attività b è stata avviata circa 3 secondi fa, è terminata più o meno allo stesso tempo, come (a)
  • il testo appare
Problemi correlati