Non capisco bene la differenza tra Task.Waite await.
Ho qualcosa di simile alle seguenti funzioni in un servizio WebAPI ASP.NET:
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
}
}
Dove si Getbloccherà.
Cosa potrebbe causare questo? Perché questo non causa problemi quando utilizzo un'attesa di blocco anziché await Task.Delay?
Task.Delay(1).Wait()è praticamente la stessa cosa di Thread.Sleep(1000). Nel codice di produzione effettivo è raramente appropriato.
WaitAllcausando il deadlock. Vedi il link al mio blog nella mia risposta per maggiori dettagli. Dovresti usare await Task.WhenAllinvece.
ConfigureAwait(false)una sola chiamata per Baro Rosnon si bloccherà, ma perché hai un enumerabile che sta creando più di una e che sta aspettando su tutte quelle, la prima barra bloccherà la seconda. Se await Task.WhenAllinvece di attendere tutte le attività, in modo da non bloccare il contesto ASP, vedrai il metodo tornare normalmente.
.ConfigureAwait(false) fino in fondo all'albero fino a quando non si blocca, in questo modo nulla sta mai cercando di tornare al contesto principale; avrebbe funzionato. Un'altra opzione sarebbe quella di creare un contesto di sincronizzazione interno. Link . Se lo metti Task.WhenAlldentro, AsyncPump.Runsi bloccherà efficacemente tutto senza che tu ne abbia bisogno da ConfigureAwaitnessuna parte, ma probabilmente è una soluzione troppo complessa.
Task.Delay(1).Wait()quale è abbastanza buono.