c# asynchronous task wait async-await

c# - espera Task.Delay() vs. Task.Delay(). Wait()



task delay c# (1)

En C # tengo los siguientes dos ejemplos simples:

[Test] public void TestWait() { var t = Task.Factory.StartNew(() => { Console.WriteLine("Start"); Task.Delay(5000).Wait(); Console.WriteLine("Done"); }); t.Wait(); Console.WriteLine("All done"); } [Test] public void TestAwait() { var t = Task.Factory.StartNew(async () => { Console.WriteLine("Start"); await Task.Delay(5000); Console.WriteLine("Done"); }); t.Wait(); Console.WriteLine("All done"); }

El primer ejemplo crea una tarea que imprime "Inicio", espera 5 segundos imprime "Hecho" y luego finaliza la tarea. Espero a que la tarea termine y luego imprimo "Todo listo". Cuando ejecuto la prueba, lo hago como se esperaba.

La segunda prueba debe tener el mismo comportamiento, excepto que la espera dentro de la tarea debe ser no bloqueante debido al uso de asincrónico y esperar. Pero esta prueba solo imprime "Inicio" y luego inmediatamente "Todo listo" y "Hecho" nunca se imprime.

No sé por qué tengo este comportamiento: S Cualquier ayuda sería apreciada mucho :)


La segunda prueba tiene dos tareas anidadas y está esperando la más externa, para solucionar esto debe usar t.Result.Wait() . t.Result obtiene la tarea interna.

El segundo método es más o menos equivalente a esto:

public void TestAwait() { var t = Task.Factory.StartNew(() => { Console.WriteLine("Start"); return Task.Factory.StartNew(() => { Task.Delay(5000).Wait(); Console.WriteLine("Done"); }); }); t.Wait(); Console.WriteLine("All done"); }

Al llamar a t.Wait() , está esperando la tarea más externa que se devuelve inmediatamente.

La forma en última instancia ''correcta'' de manejar este escenario es renunciar al uso de Wait y simplemente usar await . Wait puede causar problemas de interbloqueo una vez que haya adjuntado una IU a su código asíncrono.

[Test] public async Task TestCorrect() //note the return type of Task. This is required to get the async test ''waitable'' by the framework { await Task.Factory.StartNew(async () => { Console.WriteLine("Start"); await Task.Delay(5000); Console.WriteLine("Done"); }).Unwrap(); //Note the call to Unwrap. This automatically attempts to find the most Inner `Task` in the return type. Console.WriteLine("All done"); }

Mejor aún solo use Task.Run para iniciar su operación asincrónica:

[TestMethod] public async Task TestCorrect() { await Task.Run(async () => //Task.Run automatically unwraps nested Task types! { Console.WriteLine("Start"); await Task.Delay(5000); Console.WriteLine("Done"); }); Console.WriteLine("All done"); }