Middle+
É possível chamar código assíncrono de forma síncrona?
sobes.tech IA
Resposta da IA
Sim, é possível, mas isso pode causar problemas, especialmente deadlocks.
Formas de chamar código assíncrono de forma síncrona:
-
Uso da propriedade
Resultou do métodoWait()em um objetoTask.// Chamada síncrona de um método assíncrono Task.Run(async () => await SomeAsyncTask()).Wait(); // Obter o resultado de um método assíncrono de forma síncrona var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Uso de
GetAwaiter().GetResult():// Chamada síncrona de um método assíncrono com obtenção do resultado var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Desvantagens dessa abordagem:
- Deadlocks: O problema mais comum, especialmente em threads de interface gráfica ou contextos ASP.NET com sincronização de contexto.
Wait()eResultbloqueiam a thread atual esperando a conclusão da tarefa. Se o método assíncrono tentar capturar o contexto de sincronização bloqueado para continuar apósawait, ocorre um deadlock. - Redução de desempenho e escalabilidade: Bloquear threads ao invés de usar operações assíncronas consome mais recursos e reduz a capacidade do aplicativo de lidar com múltiplas requisições simultâneas (por exemplo, em aplicações web).
- Comportamento não intuitivo: Misturar código assíncrono e síncrono pode tornar o fluxo de execução difícil de entender e depurar.
Na maioria dos casos, a abordagem correta é usar await para continuar a execução assíncrona ou, se necessário executar código assíncrono na entrada do aplicativo (por exemplo, Main), usar Task.Run() junto com Wait() ou tornar Main assíncrono, se a versão do C# suportar (async Task Main).
Exemplo de chamada segura de código assíncrono de um método síncrono, usando Task.Run para mover a execução para o pool de threads:
// Chamada segura de método assíncrono de um contexto síncrono
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Chamada segura de método assíncrono com resultado
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;