.Continuar comienza antes de que se complete la tarea

Tengo el siguiente código en C #, VS2012, WPF 4.5. Mi expectativa sería que, .ContinueWith , se ejecutará después de que la tarea haya finalizado por completo (ese es el propósito de una continuación, ¿no?).

Esto debería resultar en un valor de 2 en finalResult .

 int myTestInt = 0; Task task = Task.Factory.StartNew(async () => { myTestInt = 1; await Task.Delay(TimeSpan.FromSeconds(6)); myTestInt = 2; }).ContinueWith(_ => { int finalResult = myTestInt; }); 

De hecho, finalResult se asigna un valor de 1 en su lugar. Así que parece que la continuación ya comenzó en la statement de await .

¿Es este el comportamiento pretendido? ¿Me estoy perdiendo de algo? ¿No puedo confiar en ContinueWith para comenzar después de que una tarea haya finalizado por completo?

Actualizar:

La respuesta de Justin me inspiró a verificar lo siguiente:

 int myTestInt = 0; Task task=Task.Factory.StartNew(async () => { myTestInt = 1; await Task.Delay(TimeSpan.FromSeconds(6)); myTestInt = 2; }); task.Wait(); int result2 = myTestInt; 

finalResult aún se establece en 1. ¿No hay forma de esperar de manera confiable que una tarea que contiene la await s se complete?

Cuando pasa un delegado async a Task.Factory.StartNew , la Task devuelta solo representa la primera parte de ese delegado (hasta el momento en que await algo que aún no se ha completado).

Sin embargo, si pasa un delegado async al nuevo método Task.Run (que se incluyó por este motivo), la Task devuelta representa el delegado completo. Así que puedes usar ContinueWith como esperas. (Aunque await suele ser una mejor opción que ContinueWith ).

Para obtener más información sobre StartNew vs Run , consulte la publicación de Stephen Toub sobre el tema .

La espera inmediatamente devolverá el control a la función de llamada, que en este caso es el inicio de su tarea. Esto significa que la tarea luego completará y ejecutará el ContinueWith. Si realmente desea que la tarea se complete antes de ContinueWith, no espere a que aparezca Task.Delay.

Vi esto en la MSDN: 🙂

 public async void button1_Click(object sender, EventArgs e) { pictureBox1.Image = await Task.Run(async() => { using(Bitmap bmp1 = await DownloadFirstImageAsync()) using(Bitmap bmp2 = await DownloadSecondImageAsync()) return Mashup(bmp1, bmp2); }); } 

Así que no olvides el “async () ” !!!