Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

239
Views
¿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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!