Pregunta ¿Async espera la palabra clave equivalente a un ContinueWith lambda?


¿Podría alguien tener la amabilidad de confirmar si he entendido que Async aguarda correctamente la palabra clave? (Usando la versión 3 del CTP)

Hasta ahora he descubierto que insertar la palabra clave await antes de una llamada a un método esencialmente hace dos cosas, A. Crea una devolución inmediata y B. Crea una "continuación" que se invoca al completar la invocación del método asincrónico. En cualquier caso, la continuación es el resto del bloque de código para el método.

Entonces, lo que me pregunto es si estos dos bits de código son técnicamente equivalentes, y si es así, ¿esto significa básicamente que la palabra clave await es idéntica a la de crear un ContinueWith Lambda (es decir, básicamente es un atajo de compilación para uno)? Si no es así, ¿cuáles son las diferencias?

bool Success =
    await new POP3Connector(
        "mail.server.com", txtUsername.Text, txtPassword.Text).Connect();
// At this point the method will return and following code will
// only be invoked when the operation is complete(?)
MessageBox.Show(Success ? "Logged In" : "Wrong password");

VS

(new POP3Connector(
    "mail.server.com", txtUsername.Text, txtPassword.Text ).Connect())
.ContinueWith((success) =>
    MessageBox.Show(success.Result ? "Logged In" : "Wrong password"));

76
2018-01-07 03:53


origen


Respuestas:


La idea general es correcta: el resto del método se convierte en una especie de continuación.

los publicación de blog "vía rápida" tiene detalles sobre cómo async/await la transformación del compilador funciona.

Diferencias, fuera de mi cabeza:

los await la palabra clave también hace uso de un concepto de "contexto de programación". El contexto de programación es SynchronizationContext.Current si existe, recurrir a TaskScheduler.Current. La continuación se ejecuta en el contexto de programación. Entonces, una aproximación más cercana sería pasar TaskScheduler.FromCurrentSynchronizationContext dentro ContinueWith, recurriendo a TaskScheduler.Current si necesario.

El actual async/await la implementación se basa en la coincidencia de patrones; usa un patrón "a la espera" que permite esperar otras cosas además de las tareas. Algunos ejemplos son las API asíncronas WinRT, algunos métodos especiales como Yield, Rx observables, y tomacorrientes especiales que no golpean el GC tan fuerte. Las tareas son poderosas, pero no son las únicas esperables.

Nos viene a la mente una pequeña y pequeña diferencia insignificante: si lo agitable ya está completo, entonces el async el método en realidad no regresa en ese punto; continúa sincrónicamente Entonces es como pasar TaskContinuationOptions.ExecuteSynchronously, pero sin los problemas relacionados con la pila.


76
2018-01-07 04:39



Es "esencialmente" eso, pero el código generado hace estrictamente más que eso. Para obtener muchos más detalles sobre el código generado, recomiendo encarecidamente la serie Eduasync de Jon Skeet:

http://codeblog.jonskeet.uk/category/eduasync/

En particular, la publicación # 7 entra en lo que se genera (a partir de CTP 2) y por qué, así que probablemente sea una buena opción para lo que estás buscando en este momento:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

EDITAR: Creo que es probable que sea más detallado que lo que estás buscando de la pregunta, pero si te preguntas cómo son las cosas cuando tienes múltiples esperanzas en el método, eso está cubierto en la publicación # 9 :)

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/


8
2018-01-07 04:38