2011-05-13 14 views
17

Me estoy divirtiendo trabajando con System.Threading.Tasks. Muchas de las muestras de código que veo, sin embargo, se ven así:¿Debo deshacerme de una tarea?

Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork()) 
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning) 
Task.WaitAll(lcTask, lcTaskLong) 

Esa es la extensión de la muestra.
Las tareas implementan IDisposable, así que obviamente se supone que debo deshacerme de ellas, pero ¿qué ocurre si solo quiero "disparar y olvidar"?

Si no me deshago, ¿voy a filtrar hilos/asas/memoria/karma? ¿Estoy usando tareas "incorrectas"? (¿Debería simplemente usar un delegado y dejar las tareas en paz?)

¿Puedo disponer de un ContinueWith()? (Eso parece como jugar a la ruleta rusa.)

Respuesta

18

Mientras que la regla normal de oro es siempre llamar Dispose() en todas las implementaciones IDisposable, Task y Task<T> son a menudo un caso en el que es mejor dejar que el finalizador hacerse cargo de esto.

El motivo Tarea implementa IDisposable se debe principalmente a un WaitHandle interno. Esto es necesario para permitir que las continuaciones de tareas funcionen correctamente y solo se usen cuando haya una continuación en una Tarea. Si no hay continuación, el método de eliminación de la tarea no tiene ningún efecto real, por lo que en este caso no es necesario.

Dicho esto, en la mayoría de los casos donde hay una continuación de Tarea, a menudo es muy, muy difícil escribir su código de una manera que le permite llamar apropiadamente a Dispose(). Normalmente, las instrucciones de uso no funcionan con las instancias de tareas, ya que la llamada a la tarea suele ser de naturaleza asincrónica. Es muy fácil deshacerse de la tarea demasiado pronto, especialmente cuando se utiliza la instrucción using.

Si, en su caso, es relativamente simple mantener una referencia a la Tarea y llamar a Dispose() correctamente, lo haría. Sin embargo, si esto hace que su lógica se vuelva mucho más compleja, normalmente pretendería que Tarea no es IDisposable, y permitiría que se limpie en el finalizador para la Tarea.

Para más detalles, recomendaría reading this thread on the MSDN forums donde Stephen Toub describe por qué la Tarea implementa IDisposable en detalle, y proporciona una guía similar a mi sugerencia anterior.

+1

Y ... \t \t [CodeAnalysis.SuppressMessage ("Microsoft.Reliability", "CA2000", Justificación = "http://stackoverflow.com/questions/5985973/do-i-need-to-dispose-of -a-task ")] – GarethOwen

+2

A juzgar por el enlace de Stephen Toub al que enlazas, creo que lo tienes al revés cuando dices" [el identificador de espera] es necesario para permitir que las continuas de tareas funcionen correctamente, y solo se usa cuando hay una continuación de una tarea. Si no hay continuación, el método de eliminación de la tarea no tiene ningún efecto real ... "Pero de acuerdo con Toub," Task.Dispose existe debido a la tarea que potencialmente envuelve un identificador de evento ... Si todo lo que estás haciendo está usando continuaciones, ese identificador de evento nunca se asignará y el valor de Dispose disminuirá en gran medida ". es decir, el reverso de lo que implica arriba. –

Cuestiones relacionadas