2011-11-16 8 views
8

Digamos que tengo un procesador cuyo trabajo es conservar los archivos en el disco. Esto se ejecuta como Task mientras se observa un BlockingCollection<T> para que los archivos se procesen.Prácticas recomendadas de cancelación de tareas

Cuando la tarea se cancela y todavía hay archivos que deben guardarse en el disco, ¿cuál sería una buena práctica para hacerlo?

Sería conveniente dejar la tarea justo antes de salir rápidamente escribir los archivos restantes en el disco aunque no estoy seguro de si esto entra en conflicto con la filosofía de cancelar una tarea (ya que la cancelación debe ocurrir lo más rápido posible) .

Otra opción es tener un segundo procedimiento después de cancelar la tarea cuyo trabajo es escribir los archivos restantes en el disco.

Código ejemplo:

class FileProcessor 
{ 
    private readonly BlockingCollection<Stream> input; 

    public FileProcessor(BlockingCollection<Stream> input) 
    { 
     _input = input; 
    } 

    public Task Run(CancellationToken cancellationToken, 
     BlockingCollection<Stream> input) 
    { 
     return Task.Factory.StartNew(() => 
     { 
      foreach (Stream stream in 
         input.GetConsumingEnumerable(cancellationToken)) 
      { 
       WriteToDisk(stream); 
      } 

      // Should I call WriteRemaining here or should I have 
        // a process running after this task exited which 
        // will call WriteRemaining 
      WriteRemaining(); 
     }); 
    } 

    public void WriteRemaining() 
    { 
     foreach (Stream stream in input)  
     { 
      WriteToDisk(stream); 
     } 
    } 
} 

Sé que esto es un poco de una pregunta abierta, la aplicación/requisitos/cantidad de archivos para escribir también juegan un papel, pero estoy buscando la pauta general/mejor prácticas aquí.

+0

No creo que realmente desee "Cancelar" en este caso, creo que solo desea detener el procesamiento, lo que podría lograr fácilmente con un semáforo simple en cualquier nuevo inicio. Para decir "Cancelar" implica detener inmediatamente para otra cosa, si quieres una "Parada" segura, entonces puedes lograr eso fuera de la cancelación de material potencialmente. Pero no estoy seguro de si esa es una mejor práctica ... –

+0

¿no debería la carga de completar el resto de las escrituras estar pendiente de la cancelación? IMO Write Remaining debe estar en el método Register del objeto CancellationToken –

+0

No existe ninguna obligación contractual para que Cancel cause una terminación rápida o incluso cause la cancelación. Si su proceso no es compatible con la cancelación, puede ignorar la cancelación y simplemente completarla satisfactoriamente. –

Respuesta

9

Cancellation is a cooperative action cuando se trabaja con la Biblioteca de tareas paralelas, y sí, se recomienda cancelar con una operación rápida.

Recuerde, esto es una cancelación , no una cancelación y limpieza. Si tiene operaciones adicionales que debe realizar como resultado de una cancelación, entonces esas operaciones deberían ocurrir fuera de la tarea original que se canceló.

Tenga en cuenta que esto no le impide llamar ContinueWith y la realización de una operación en una nueva Task que comprueba para ver si los retornos IsCanceled propertytrue y después realiza la limpieza en base a eso.

El punto clave aquí es que no desea bloquear el Task original que se canceló, pero puede iniciar un nuevo Task para realizar cualquier limpieza que deba hacer como resultado de la cancelación.

Cuestiones relacionadas