No entiendo la diferencia entre Task.Waity await.
Tengo algo similar a las siguientes funciones en un servicio ASP.NET WebAPI:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
¿Dónde Getquedará estancado?
Que podria causar esto? ¿Por qué esto no causa un problema cuando uso una espera de bloqueo en lugar de hacerlo await Task.Delay?
Task.Delay(1).Wait()es básicamente exactamente lo mismo que Thread.Sleep(1000). En el código de producción real rara vez es apropiado.
WaitAllestá causando el punto muerto. Vea el enlace a mi blog en mi respuesta para más detalles. Deberías usar await Task.WhenAllen su lugar.
ConfigureAwait(false)una sola llamada a un punto muerto Baro Rosno lo hará, pero debido a que tiene un número enumerable que está creando más de uno y luego espera a todos, la primera barra bloqueará el segundo. Si en await Task.WhenAlllugar de esperar todas las tareas, para no bloquear el contexto ASP, verá que el método regresa normalmente.
.ConfigureAwait(false) todo el camino hasta el árbol hasta que se bloquea, de esa manera nada está siempre tratando de volver al contexto principal; eso funcionaria. Otra opción sería activar un contexto de sincronización interna. Enlace . Si lo coloca Task.WhenAlldentro AsyncPump.Run, bloqueará efectivamente todo el proceso sin que lo necesite en ConfigureAwaitningún lado, pero esa es probablemente una solución demasiado compleja.
Task.Delay(1).Wait()que es lo suficientemente bueno.