2012-09-19 10 views
5

estoy siguiendo el tutorial await en el MSDN, y estoy tratando de averiguar la diferencia entre usar await como una declaraciónfrente a la utilización await como una expresión . Toda esta espera asincrónica está inclinando mi mente y no puedo encontrar ningún ejemplo para este caso en particular.esperan declaración frente a la expresión

Básicamente, quería ver cómo usar múltiples await s de forma asíncrona, lo que significa que no quiero tener que esperar a que el primero se complete antes de que comience el segundo. Esto, para mí, en contra del propósito de asincronía, para empezar:

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"; 
} 

Sin embargo, con un cambio sutil que sólo tarda 3 segundos en total para los dos "Terminado" s a aparecer, que es lo que me gustaría - los dos await s ejecutando realmente de forma asíncrona:

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

Mi pregunta es, ¿por qué estos se comportan de manera diferente? ¿Qué punto sutil me falta aquí?

Respuesta

11

En primer lugar, es necesario distinguir entre el paralelismo y asincronía. En el primer caso, fácilmente podría valer la pena realizar las operaciones de forma sincrónica (y de hecho la segunda operación puede depender de los resultados del primero) para liberar el hilo de la interfaz de usuario, etc.

Pero en cuanto a por qué se comportan de manera diferente - await es solo una expresión. Es el tipo de expresión que puede aparecer como una declaración, pero se comportará de la misma manera, al igual que llamar a un método que devuelve una cadena, pero ignorando el valor de retorno. Usted puede ver eso cambiando su primer código a:

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

var b = WaitAsynchronouslyAsync(); 
await b; 

Eso todavía tomará 6 segundos. El punto es que solo está comenzando la segunda operación asíncrona después de que ha esperado para que termine la primera. En su segundo ejemplo, ambas operaciones asincrónicas ocurren al mismo tiempo.

Todavía se puede hacer eso y asignar el valor a una variable, sólo tiene que recordar las awaitables:

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

Así que, básicamente, la diferencia no tiene que ver con la declaración/expresión - es para ver si la secuencia es start/await/start/await o start/start/await/await.

+0

Su última edición me hizo comprender, gracias - la secuencia es la cuestión. Debería haberme dado cuenta de que ambas son expresiones. –

4

En ambas situaciones, la palabra clave await presenta asincronía. La razón por la que ve la diferencia es que en el caso 1 usted inicia ambas tareas secuencialmente, donde en el caso 2 las deja ejecutar en paralelo.

Tal vez una explicación paso a paso de ambas situaciones borra las cosas

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

Lo que sucede aquí es:

  • se espera una tarea (a) se inició
  • tarea A (control se devuelve a la persona que llama)
  • cuando la tarea a finaliza después de 3 segundos, el método se reanuda; tarea (b) se inicia
  • tarea b está a la espera (control se devuelve a la persona que llama)
  • cuando la tarea b está terminado después de otros 3 segundos, aparece el texto

En el segundo caso:

se inicia
var a = WaitAsynchronouslyAsync();  
var b = WaitAsynchronouslyAsync();  
await a;  
await b;  
  • tarea (a)
  • tarea (b) se inicia
  • tarea (a) es 'aw aited '(es decir, se devuelve el control a la persona que llama)
  • cuando la tarea (a) finaliza después de 3 segundos, se espera la tarea (b)
  • ya que la tarea b se inició hace aproximadamente 3 segundos, ha terminado más o menos al mismo tiempo que (a)
  • el texto aparece
Cuestiones relacionadas