Middle+
¿Se puede llamar a código asíncrono de forma sincrónica?
sobes.tech AI
Respuesta de la IA
Sí, es posible, pero puede causar problemas, en particular, bloqueos.
Formas de llamar de manera síncrona a código asíncrono:
-
Uso de la propiedad
Resulto del métodoWait()en un objetoTask.// Llamada síncrona a un método asíncrono Task.Run(async () => await SomeAsyncTask()).Wait(); // Obtener el resultado de un método así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():// Llamada síncrona a un método asíncrono con obtención del resultado var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Desventajas de este enfoque:
- Bloqueos: El problema más común, especialmente en hilos de interfaz de usuario o contextos ASP.NET con sincronización de contexto.
Wait()yResultbloquean el hilo actual esperando que la tarea termine. Si el método asíncrono intenta capturar el contexto de sincronización bloqueado para continuar después deawait, se produce un bloqueo. - Reducción del rendimiento y escalabilidad: Bloquear hilos en lugar de usar operaciones asíncronas consume más recursos y reduce la capacidad de la aplicación para manejar múltiples solicitudes simultáneas (por ejemplo, en aplicaciones web).
- Comportamiento no evidente: Mezclar código asíncrono y síncrono puede hacer que el flujo de ejecución sea difícil de entender y depurar.
En la mayoría de los casos, la mejor práctica es usar await para continuar la ejecución asíncrona o, si es necesario ejecutar código asíncrono en el punto de entrada de la aplicación (por ejemplo, Main), usar Task.Run() junto con Wait() o hacer que Main sea asíncrono, si la versión de C# lo soporta (async Task Main).
Ejemplo de llamada segura a código asíncrono desde un método síncrono, usando Task.Run para mover la ejecución al pool de hilos:
// Llamada segura a un método asíncrono desde un contexto síncrono
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Llamada segura a un método asíncrono con resultado
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;