¿Cómo puedo esperar a que un void async
método termine su trabajo?
Por ejemplo, tengo una función como la siguiente:
async void LoadBlahBlah()
{
await blah();
...
}
ahora quiero asegurarme de que todo se haya cargado antes de continuar en otro lugar.
c#
asynchronous
MBZ
fuente
fuente
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
es engañosa. Esto no espera la finalización de la función asíncronablah
, solo espera la creación (trivial) de la tarea y continúa inmediatamente antes de que seblah()
haya completado.Thread.Sleep
no es asíncrono. Esta pregunta se trata de esperar unaasync void
función, por ejemploasync void blah() { Task.Delay(10000); }
Si puede cambiar la firma de su función a,
async Task
entonces puede usar el código presentado aquífuente
La mejor solución es usar
async Task
. Debe evitarasync void
por varias razones, una de las cuales es la componibilidad.Si no se puede hacer que el método regrese
Task
(p. Ej., Es un controlador de eventos), puede usarSemaphoreSlim
para que la señal del método esté a punto de salir. Considera hacer esto en unfinally
bloque.fuente
haga un AutoResetEvent, llame a la función, luego espere en AutoResetEvent y luego configúrelo dentro de vacío asíncrono cuando sepa que está hecho.
También puede esperar una Tarea que regrese de su vacío asíncrono
fuente
Realmente no necesita hacer nada manualmente, la
await
palabra clave detiene la ejecución de la función hasta queblah()
regrese.T
es el tipo de objetoblah()
devuelveRealmente no puede
await
unavoid
función, asíLoadBlahBlah()
que no puede servoid
fuente
LoadBlahBlah()
que termine, noblah()
Sé que esta es una vieja pregunta, pero aún sigo siendo un problema, y todavía no hay una solución clara para hacerlo correctamente cuando se usa async / wait en un método de firma vacío async.
Sin embargo, noté que .Wait () funciona correctamente dentro del método void.
y como async void y void tienen la misma firma, es posible que deba hacer lo siguiente.
Lo suficientemente confuso como async / await no se bloquea en el siguiente código.
Cuando descompila su código, supongo que el vacío asíncrono crea una Tarea interna (al igual que la Tarea asíncrona), pero dado que la firma no admite devolver esas Tareas internas
Esto significa que internamente el método vacío asíncrono aún podrá "esperar" los métodos asíncronos internos. pero externamente no puede saber cuándo se completa la tarea interna.
Entonces, mi conclusión es que el vacío asíncrono funciona según lo previsto, y si necesita comentarios de la Tarea interna, entonces debe usar la firma de la Tarea asíncrona en su lugar.
espero que mis divagaciones tengan sentido para cualquiera que también busque respuestas.
Editar: hice un código de ejemplo y lo descompuse para ver qué está pasando realmente.
Se convierte en (editar: sé que el código del cuerpo no está aquí sino en las máquinas de estado, pero las máquinas de estado eran básicamente idénticas, así que no me molesté en agregarlas)
ni AsyncVoidMethodBuilder ni AsyncTaskMethodBuilder tienen realmente ningún código en el método Start que les sugiera que bloqueen y siempre se ejecuten de forma asíncrona después de que se inicien.
lo que significa que sin la Tarea de retorno, no habría forma de verificar si está completa.
como se esperaba, solo inicia la Tarea ejecutándose de forma asíncrona y luego continúa en el código. y la Tarea asíncrona, primero comienza la Tarea y luego la devuelve.
así que supongo que mi respuesta sería nunca usar el vacío asíncrono, si necesita saber cuándo se realiza la tarea, para eso está la tarea asíncrona.
fuente