Kann asynchroner Code synchron aufgerufen werden?
sobes.tech KI
Antwort von AI
Ja, es ist möglich, aber es kann zu Problemen führen, insbesondere zu Deadlocks.
Methoden, um asynchronen Code synchron aufzurufen:
-
Verwendung der Eigenschaft
Resultoder der MethodeWait()an einemTask-Objekt.// Synchroner Aufruf einer asynchronen Methode Task.Run(async () => await SomeAsyncTask()).Wait(); // Synchroner Zugriff auf das Ergebnis einer asynchronen Methode var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Verwendung von
GetAwaiter().GetResult():// Synchroner Aufruf einer asynchronen Methode mit Ergebnis var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Nachteile dieses Ansatzes:
- Deadlocks: Das häufigste Problem, besonders in UI-Threads oder ASP.NET-Kontexten mit Synchronisationskontext.
Wait()undResultblockieren den aktuellen Thread, während die Aufgabe abgeschlossen wird. Wenn die asynchrone Methode versucht, den geblockierten Synchronisationskontext zu erfassen, entsteht ein Deadlock. - Leistungs- und Skalierungsverschlechterung: Das Blockieren von Threads anstelle der Verwendung asynchroner Operationen verbraucht mehr Ressourcen und verringert die Fähigkeit der Anwendung, mehrere gleichzeitige Anfragen zu verarbeiten (z.B. in Webanwendungen).
- Nicht offensichtliches Verhalten: Das Mischen von asynchronem und synchronem Code kann den Ablauf schwer verständlich und debugbar machen.
In den meisten Fällen ist die richtige Vorgehensweise, await zu verwenden, um die asynchrone Ausführung fortzusetzen, oder, wenn asynchroner Code im Einstiegspunkt der Anwendung ausgeführt werden muss (z.B. Main), Task.Run() in Kombination mit Wait() zu verwenden oder Main asynchron zu machen, wenn die C#-Version dies unterstützt (async Task Main).
Beispiel für einen sicheren Aufruf von asynchronem Code aus einer synchronen Methode, bei Verwendung von Task.Run, um die Ausführung in den Threadpool zu verschieben:
// Sicherer Aufruf einer asynchronen Methode aus einem synchronen Kontext
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Sicherer Aufruf einer asynchronen Methode mit Ergebnis
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;