Middle+
Lze volat asynchronní kód synchronně?
sobes.tech AI
Odpověď od AI
Ano, je to možné, ale může to způsobit problémy, zejména deadlocky.
Způsoby, jak synchronně volat asynchronní kód:
-
Použití vlastnosti
Resultnebo metodyWait()na objektuTask.// Synchronní volání asynchronní metody Task.Run(async () => await SomeAsyncTask()).Wait(); // Získání výsledku asynchronní metody synchronně var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Použití
GetAwaiter().GetResult():// Synchronní volání s výsledkem var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Nevýhody tohoto přístupu:
- Deadlock: Nejčastější problém, zejména v UI vláknech nebo v ASP.NET kontextech s synchronizačním kontextem.
Wait()aResultblokují aktuální vlákno, čekají na dokončení úkolu. Pokud se asynchronní metoda pokusí zachytit zablokovaný kontext pro pokračování poawait, vznikne deadlock. - Zhoršení výkonu a škálovatelnosti: Blokování vláken místo použití asynchronních operací spotřebovává více zdrojů a snižuje schopnost aplikace zpracovávat více požadavků současně (například ve webových aplikacích).
- Nezřetelné chování: Míchání asynchronního a synchronního kódu může ztížit pochopení a ladění toku programu.
Ve většině případů je správný přístup používat await k pokračování asynchronního provádění nebo, pokud je nutné spustit asynchronní kód v vstupním bodě aplikace (například Main), použít Task.Run() ve spojení s Wait() nebo udělat Main asynchronní, pokud to verze C# podporuje (async Task Main).
Příklad bezpečného volání asynchronního kódu ze synchronní metody s použitím Task.Run k přesunutí provádění do thread poolu:
// Bezpečné volání asynchronní metody ze synchronního kontextu
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Bezpečné volání asynchronní metody s výsledkem
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;