pasar - retornar un valor de un formulario c#
¿Cuál es la diferencia entre devolver el vacío y devolver una Tarea? (4)
En caso de que la persona que llama desee esperar en la tarea o agregar una continuación.
De hecho, la única razón para devolver el void
es si no puede devolver la Task
porque está escribiendo un controlador de eventos.
Al observar varias muestras de CTP C # Async, veo algunas funciones de sincronización que devuelven el void
y otras que devuelven la Task
no genérica. Puedo ver por qué devolver una Task<MyType>
es útil para devolver datos a la persona que llama cuando se completa la operación asincrónica, pero las funciones que he visto que tienen un tipo de devolución de Task
nunca devuelven ningún dato. ¿Por qué no devolver el void
?
Las respuestas de SLaks y Killercam son buenas; Pensé que solo agregaría un poco más de contexto.
Su primera pregunta es esencialmente sobre qué métodos se pueden marcar como async
.
Un método marcado como
async
puede devolvervoid
,Task
oTask<T>
. Cuáles son las diferencias entre ellos?
Se puede esperar un método asincrónico de Regreso a Task<T>
, y cuando la tarea finalice ofrecerá una T.
Se puede esperar un método asincrónico de devolución de Task
, y cuando la tarea finalice, la ejecución de la tarea está programada para ejecutarse.
No se puede esperar un método asíncrono que devuelve el void
; es un método de "fuego y olvídate". Funciona de forma asíncrona, y no tiene forma de saber cuándo se hace. Esto es más que un poco raro; como dice SLaks, normalmente solo harías eso al crear un controlador de eventos asíncrono. El evento se dispara, el controlador se ejecuta; nadie va a "esperar" la tarea devuelta por el manejador de eventos porque los manejadores de eventos no devuelven tareas, e incluso si lo hicieran, ¿qué código usaría la Tarea para algo? Por lo general, no es el código de usuario el que transfiere el control al controlador en primer lugar.
Su segunda pregunta, en un comentario, es esencialmente sobre lo que se puede await
:
¿Qué tipo de métodos se pueden
await
? ¿Se puedeawait
método de devolución de nulidad?
No, no se puede esperar un método de devolución de vacío. El compilador traduce await M()
en una llamada a M().GetAwaiter()
, donde GetAwaiter
podría ser un método de instancia o un método de extensión. El valor esperado tiene que ser uno para el que pueda obtener un awaiter; claramente un método de devolución de vacío no produce un valor del que pueda obtener un awaiter.
Los métodos de recuperación de Task
pueden producir valores aguardables. Anticipamos que los terceros querrán crear sus propias implementaciones de objetos similares a Task
que puedan esperarse, y podrá esperarlos. Sin embargo, no se le permitirá declarar métodos async
que devuelvan cualquier cosa que no sea void
, Task
o Task<T>
.
(ACTUALIZACIÓN: Mi última oración puede ser falsificada por una versión futura de C #; hay una propuesta para permitir tipos de devolución que no sean tipos de tareas para métodos asíncronos).
(ACTUALIZACIÓN: la función mencionada anteriormente ingresó en C # 7.)
Métodos que vuelven La Task
y la Task<T>
pueden componer, lo que significa que puedes await
dentro de un método async
.
async
métodos async
que devuelven el void
no son compostables, pero tienen otras dos propiedades importantes:
- Se pueden usar como controladores de eventos.
- Representan una operación asincrónica de "nivel superior".
El segundo punto es importante cuando se trata de un contexto que mantiene un recuento de las operaciones asincrónicas sobresalientes.
El contexto ASP.NET es uno de esos contextos; si usa métodos de Task
asíncronas sin esperarlos de un método de anync void
, la solicitud de ASP.NET se completará demasiado pronto.
Otro contexto es el AsyncContext
que escribí para pruebas unitarias (disponible here ): el método AsyncContext.Run
seguimiento del recuento de operaciones pendientes y lo devuelve cuando es cero.
Tipo Task<T>
es el tipo de caballo de batalla de Task Parallel Library (TPL), representa el concepto de "algún trabajo / trabajo que va a producir un resultado de tipo T
en el futuro". El concepto de "trabajo que completará en el futuro pero no arroja ningún resultado" está representado por el tipo de tarea no genérica.
Precisamente cómo se producirá el resultado del tipo T
es el detalle de la implementación de una tarea en particular; el trabajo puede ser transferido a otro proceso en la máquina local, a otro subproceso, etc. Las tareas TPL normalmente se procesan en subprocesos de trabajo desde un grupo de subprocesos en el proceso actual, pero ese detalle de implementación no es fundamental para la Task<T>
tipo; más bien, una Task<T>
puede representar cualquier operación de alta latencia que produzca una T
En base a su comentario anterior:
La expresión de await
significa "evaluar esta expresión para obtener un objeto que representa el trabajo que en el futuro producirá un resultado. Registre el resto del método actual como la devolución de llamada asociada con la continuación de esa tarea. Una vez que se produce esa tarea y la llamada Atrás está registrado, devuelve inmediatamente el control a mi interlocutor ". Esto es opuesto / en contraste con una llamada a método regular, lo que significa "recuerda lo que estás haciendo, ejecuta este método hasta que esté completamente terminado y luego retoma donde lo dejaste, ahora conoce el resultado del método".
Editar: Debería citar el artículo de Eric Lippert en octubre de 2011 en MSDN Magazine ya que fue una gran ayuda para mí en la comprensión de estas cosas en primer lugar.
Para más infromation y whitepages, consulte here .
Espero que esto sea de ayuda.