Middle+
Ar galima sinchroniškai iškviesti asinchroninį kodą?
sobes.tech AI
Atsakymas iš AI
taip, galima, bet tai gali sukelti problemų, ypač deadlock'us.
Būdai sinchroniškai iškviesti asinchroninį kodą:
-
Naudojant
Resultsavybę arbaWait()metodąTaskobjekte:// Sinchroninis asinchroninio metodo iškvietimas Task.Run(async () => await SomeAsyncTask()).Wait(); // Gauti asinchroninio metodo rezultatą sinchroniškai var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Naudojant
GetAwaiter().GetResult():// Sinchroninis asinchroninio metodo iškvietimas su rezultato gavimu var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Šio metodo trūkumai:
- Deadlock'ai: Dažniausia problema, ypač UI gijų arba ASP.NET kontekstuose, kur
Wait()irResultblokuoja esamą giją, laukdami užduoties pabaigos. Jei asinchroninė funkcija bando pagauti užblokuotą sinchronizacijos kontekstą tęsti poawait, įvyksta deadlock'as. - Našumo ir mastelio mažėjimas: Gijų blokavimas vietoje asinchroninių operacijų naudojimo naudoja daugiau išteklių ir sumažina galimybę apdoroti daug vienu metu užklausų (pvz., internetinėse programose).
- Neaiškus elgesys: Asinchroninio ir sinchroninio kodo maišymas gali padaryti programos vykdymo srautą sudėtingą suprasti ir derinti.
Dažniausiai teisingas būdas yra naudoti await asinchroniniam vykdymui tęsti arba, jei reikia vykdyti asinchroninį kodą programos įėjimo taške (pvz., Main), naudoti Task.Run() kartu su Wait() arba padaryti Main asinchroniniu, jei C# versija tai palaiko (async Task Main).
Saugus pavyzdys:
// Saugus asinchroninio metodo iškvietimas iš sinchroninio konteksto
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Saugus asinchroninio metodo iškvietimas su rezultatu
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;