Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

229
Vistas
¿Cómo evito el vacío asíncrono?

Nota: Resulta que este problema es específico de Unity.

Leí que se debía evitar el async void . Estoy tratando de hacerlo usando Result , pero mi aplicación sigue bloqueándose. ¿Cómo puedo evitar usar async void?

 public async void PrintNumberWithAwait() { int number = await GetNumber(); Debug.Log(number); //Successfully prints "5" } public void PrintNumberWithResult() { int number = GetNumber().Result; Debug.Log(number); //Application Freezes } private async Task<int> GetNumber() { await Task.Delay(1000); return 5; }

Pensé que esto era correcto, pero debo estar perdiendo algo. ¿Cómo uso async/await sin tener async void ?

Ejecuté mis pruebas por separado con el siguiente código (comenté uno a la vez):

 PrintNumberWithAwait(); PrintNumberWithResult();
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

No entendiste lo que significa el async void que se debe evitar.

No significa que nunca debas usar una tarea sin resultados adjuntos. Simplemente dice que los métodos asincrónicos que los invocan deben devolver una Task , no una void .

Simplemente tome la firma de su método asíncrono de

 public async void PrintNumberWithAwait()

y reemplace void con Task

 public async Task PrintNumberWithAwait() { int number = await GetNumber(); Debug.Log(number); //Successfully prints "5" }

Ahora los métodos de llamada tienen la opción de esperar el resultado, cuando y si así lo desean. Cualquiera:

 await PrintNumberWithAwait();

O

 Task t = PrintNumberWithAwait(); // Do other stuff // ... await t;
over 4 years ago · Santiago Trujillo Denunciar

0

Version corta

El contexto de sincronización de Unity es de un solo subproceso. Entonces:

  1. El resultado se cuelga hasta que se completa la tarea
  2. La tarea no se puede completar porque la continuación se presiona en Main Thread, que está esperando

Versión detallada

Dijiste que estás usando Unity. Unity es "99%" un marco de un solo subproceso. Así que supongo que este código se ejecuta en Main, UI Thread.

Pasemos a lo que hace su código en detalle, al ejecutar PrintNumberWithResult().

  1. [Hilo principal] Desde PrintNumberWithResult() llamas a GetNumber()
  2. [Hilo principal] Ejecutas await Task.Delay()
  3. [Subproceso principal] El código debajo de la línea de espera (el retorno 5) se "empuja" a una "Lista de código" para ejecutar después de que se complete la tarea (el retraso). Pequeña información : este tipo de lista de "código de continuación" es manejada por una clase llamada SynchronizationContext (es una cosa ac #, no una cosa de Unity). Puedes pensar en esta clase como el tipo que dice CÓMO y CUÁNDO se llama el código entre esperas. La implementación estándar de .NET utiliza un grupo de subprocesos (por lo tanto, un conjunto de subprocesos) que ejecutará el código después de que se complete la tarea. Es como una "devolución de llamada avanzada". Ahora en Unity esto es diferente. Implementaron un contexto de sincronización personalizado que garantiza que todo el código se ejecute SIEMPRE en el HILO PRINCIPAL. podemos continuar ahora
  4. [HILO PRINCIPAL] La tarea de retraso aún no se ha completado, por lo que tiene un retorno anticipado en el método PrintNumberWithResult y ejecuta el .Result, que hace que el hilo principal se cuelgue allí hasta que se complete la tarea.
  5. [Bloqueo] . 2 cosas están sucediendo en este punto. El subproceso principal está esperando que se complete la tarea. El Contexto de sincronización de Custom Unity empujó el código arriba de la espera para ser ejecutado en el Subproceso Principal. ¡Pero The Main Thread está esperando! Por lo tanto, nunca será libre de ejecutar ese código.

Solución No llamar nunca .Resultado.

Si desea disparar y olvidar una operación de tarea, use Task.Run(() => ). ¡Pero espera! ¡Esa no es una buena idea en Unity! (Tal vez esté en otras aplicaciones .NET).

Si usa Task.Run() en Unity, está forzando la ejecución del código asíncrono usando el contexto de sincronización de .NET predeterminado, que usa un grupo de subprocesos, y eso podría causar algunos problemas de sincronización si está llamando a alguna API relacionada con Unity.

Lo que desea hacer en ese caso es usar un vacío asíncrono (no realmente por razones relacionadas con el manejo de excepciones), un método de tarea asíncrona que nunca esperará (mejor), o tal vez usar una biblioteca como UniTask para espera asíncrona usando Unity (Lo mejor en mi opinión).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda