Ich verstehe den Unterschied zwischen Task.Waitund nicht ganz await.
Ich habe etwas Ähnliches wie die folgenden Funktionen in einem ASP.NET-WebAPI-Dienst:
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
}
}
Wo Getwird Deadlock.
Was könnte das verursachen? Warum verursacht dies kein Problem, wenn ich eine blockierende Wartezeit anstelle von verwende await Task.Delay?
Task.Delay(1).Wait()ist im Grunde das gleiche wie Thread.Sleep(1000). Im tatsächlichen Produktionscode ist dies selten angemessen.
WaitAllverursachst den Deadlock. Weitere Informationen finden Sie unter dem Link zu meinem Blog in meiner Antwort. Sie sollten await Task.WhenAllstattdessen verwenden.
ConfigureAwait(false)einen einzelnen Anruf zum Deadlock haben Baroder Rosnicht blockieren werden, aber weil Sie eine Aufzählung haben, die mehr als einen erstellt und dann auf all diese wartet, blockiert der erste Balken den zweiten. Wenn Sie await Task.WhenAllnicht auf alle Aufgaben warten, um den ASP-Kontext nicht zu blockieren, wird die Methode normal zurückgegeben.
.ConfigureAwait(false) gesamten Baum bis zum Blockieren hinzuzufügen. Auf diese Weise versucht nie etwas, zum Hauptkontext zurückzukehren. das würde funktionieren. Eine andere Möglichkeit wäre, einen inneren Synchronisationskontext aufzurufen. Link . Wenn Sie das Task.WhenAllin ein setzen AsyncPump.Run, wird es das Ganze effektiv blockieren, ohne dass Sie ConfigureAwaitirgendwo hin müssen, aber das ist wahrscheinlich eine zu komplexe Lösung.
Task.Delay(1).Wait()dem ist gut genug.