Unten ist eine vereinfachte Version des Codes, mit dem ich Probleme habe. Wenn ich dies in einer Konsolenanwendung ausführe, funktioniert es wie erwartet. Alle Abfragen werden parallel ausgeführt und Task.WaitAll()
wird zurückgegeben, wenn sie alle abgeschlossen sind.Task.WaitAll hängt mit mehreren erwarteten Aufgaben in ASP.NET
Wenn dieser Code jedoch in einer Webanwendung ausgeführt wird, hängt die Anforderung einfach. Wenn ich einen Debugger anschließe und alles abbringe, wird angezeigt, dass die Ausführung auf Task.WaitAll()
wartet. Und die erste Aufgabe ist abgeschlossen, aber die anderen enden nie.
Ich kann nicht herausfinden, warum es beim Ausführen in ASP.NET hängt, aber in einer Konsolenanwendung funktioniert.
public Foo[] DoWork(int[] values)
{
int count = values.Length;
Task[] tasks = new Task[count];
for (int i = 0; i < count; i++)
{
tasks[i] = GetFooAsync(values[i]);
}
try
{
Task.WaitAll(tasks);
}
catch (AggregateException)
{
// Handle exceptions
}
return ...
}
public async Task<Foo> GetFooAsync(int value)
{
Foo foo = null;
Func<Foo, Task> executeCommand = async (command) =>
{
foo = new Foo();
using (SqlDataReader reader = await command.ExecuteReaderAsync())
{
ReadFoo(reader, foo);
}
};
await QueryAsync(executeCommand, value);
return foo;
}
public async Task QueryAsync(Func<SqlCommand, Task> executeCommand, int value)
{
using (SqlConnection connection = new SqlConnection(...))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
// Set up query...
await executeCommand(command);
// Log results...
return;
}
}
}
+1. Obwohl ich den Begriff "Anfragekontext" anstelle von "Hauptthread" verwenden würde. –
@ StephenCleary Ja, es war umstritten. Ich setze Hauptthread in Anführungszeichen, weil es nicht der Hauptthread der gesamten Anwendung ist, aber man kann es sich als "Hauptthread dieser Anfrage" vorstellen. Es ist eine nützliche Art, das Problem in meinem Kopf zu denken. – Servy
Ein wichtiger Vorbehalt ist, dass die aware Task.WhenAll die AggregateException nicht auslöst; Nur eine der inneren Ausnahmen wird weitergegeben. Wenn Sie die gesamte AggregateException untersuchen möchten, müssen Sie einen Verweis auf die zurückgegebene Task von task.WhenAll speichern und die Exception-Eigenschaft explizit überprüfen. –