Kan asynchrone code synchrone worden aangeroepen?
sobes.tech AI
Antwoord van AI
Ja, het is mogelijk, maar dit kan problemen veroorzaken, vooral deadlocks.
Manieren om asyncode synchroon aan te roepen:
-
Gebruik van de
Resulteigenschap of deWait()methode op eenTaskobject.// Synchroon aanroepen van een asynchrone methode Task.Run(async () => await SomeAsyncTask()).Wait(); // Het verkrijgen van het resultaat van een asynchrone methode synchroon var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Gebruik van
GetAwaiter().GetResult():// Synchroon aanroepen van een asynchrone methode met resultaat var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Nadelen van deze aanpak:
- Deadlocks: Het meest voorkomende probleem, vooral in UI-threads of ASP.NET contexten met synchronisatiecontext.
Wait()enResultblokkeren de huidige thread, wachtend op de voltooiing van de taak. Als de asynchrone methode probeert de geblokkeerde synchronisatiecontext te pakken voor verdere uitvoering naawait, ontstaat een deadlock. - Prestatie- en schaalbaarheidsvermindering: Het blokkeren van threads in plaats van gebruik te maken van asynchrone operaties, verbruikt meer resources en vermindert de capaciteit van de applicatie om meerdere gelijktijdige verzoeken te verwerken (bijvoorbeeld in webapplicaties).
- Onzichtbaar gedrag: Het mengen van asynchrone en synchrone code kan de uitvoering moeilijk te begrijpen en debuggen maken.
In de meeste gevallen is de juiste aanpak om await te gebruiken voor het voortzetten van asynchrone uitvoering of, indien nodig, asynchrone code uit te voeren op het startpunt van de applicatie (bijvoorbeeld Main), gebruikmakend van Task.Run() in combinatie met Wait() of het asynchroon maken van Main, indien de C#-versie dit ondersteunt (async Task Main).
Voorbeeld van veilige aanroep van asynchrone code vanuit een synchrone methode, gebruikmakend van Task.Run om de uitvoering naar de threadpool te verplaatsen:
// Veilige aanroep van een asynchrone methode vanuit een synchrone context
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Veilige aanroep van een asynchrone methode met resultaat
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;