Middle+
Lehet szinkron módon hívni aszinkron kódot?
sobes.tech MI
Válasz az MI-től
Igen, lehetséges, de problémákhoz vezethet, különösen deadlockokhoz.
Az aszinkron kód szinkron hívásának módjai:
-
A
Resulttulajdonság vagy aWait()metódus használata egyTaskobjektumon.// Aszinkron metódus szinkron hívása Task.Run(async () => await SomeAsyncTask()).Wait(); // Az aszinkron metódus eredményének szinkron lekérése var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
A
GetAwaiter().GetResult()használata:// Szinkron hívás eredménnyel var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Ennek a megközelítésnek hátrányai:
- Deadlock: A leggyakoribb probléma, különösen UI szálakon vagy ASP.NET kontextusokban, ahol a szinkronizációs kontextushoz kötött. A
Wait()és aResultblokkolják az aktuális szálat, várva a feladat befejezését. Ha az aszinkron metódus megpróbálja elkapni a blokkolt szinkronizációs kontextust aawaitutáni folytatáshoz, deadlock keletkezik. - Teljesítmény- és skálázhatóságcsökkenés: A szálak blokkolása az aszinkron műveletek helyett több erőforrást igényel, és csökkenti az alkalmazás képességét, hogy több kérés egyidejűleg legyen kezelve (például webalkalmazásokban).
- Nem nyilvánvaló viselkedés: Az aszinkron és szinkron kód keverése megnehezítheti a program futásának megértését és hibakeresését.
A legtöbb esetben a helyes megközelítés az await használata az aszinkron végrehajtás folytatásához, vagy ha az aszinkron kódot az alkalmazás belépési pontján (például Main) kell futtatni, akkor Task.Run() használata Wait()-el vagy az Main aszinkronná tétele, ha a C# verzió támogatja (async Task Main).
Biztonságos példa az aszinkron kód szinkron hívására, Task.Run használatával, hogy a végrehajtást a szálak pooljára helyezzük:
// Biztonságos aszinkron hívás szinkron kontextusból
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Biztonságos aszinkron hívás eredménnyel
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;