2012-05-12 11 views
7

tengo la siguiente configuración en mi código que utiliza el TPL:TPL continuación cancelación nunca se pidió a cancelado Tarea

  • Un campo en mi clase: private CancellationTokenSource _cancellationTokenSource;
  • Este CancellationTokeSource se instatiated cada vez que creo una tarea de TPL que utiliza ese particular CancellationToken

Las tareas TPL podía comprender este aspecto:

var dataRetrievalTask = new Task<List<myType>>(() => 
      { 
       // retrieve data and do something 
       foreach (var a in retrievalMethod()) 
       { 
        if (_cancellationTokenSource.Token.IsCancellationRequested) 
         _cancellationTokenSource.Token.ThrowIfCancellationRequested(); 

         // do something if not cancelled 
        } 
       } 

       return filledListOfMyType; 

      }, _cancellationTokenSource.Token); 

      // define what shall happen if data retrievel finished without any problems 
      var writingLoadedDataToGridTask = dataRetrievalTask.ContinueWith(task => 
      { 
       // do something in case we ran to completion without error 
      }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, currentScheduler); 

      // what to do in case cancellation was performed 
      var loadingDataCancelledTask = dataRetrievalTask.ContinueWith(task => 
           { 
           someLabel.Text = "Data retrieval canceled."; 
           },_cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnCanceled, currentScheduler); 

      // what to do in case an exception/error occured 
      var loadingDataFaulted = dataRetrievalTask.ContinueWith(task => 
       { 
        someLabel.Text = string.Format("Data retrieval ended with an Error."); 
       }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, currentScheduler); 

      // when any of the continuation tasks ran through, reset ui controls/buttons etc 
      Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task => 
      { 
       // reset controls and all that 
      }, _cancellationTokenSource.Token, TaskContinuationOptions.None, currentScheduler); 


      dataRetrievalTask.Start(); 

Ahora mi problema es que cuando el _cancellationTokenSource.Cancel El método() se llama en algún lugar (en el controlador de evento .Click de un botón Cancelar) y no se llama al cuerpo/método particular de cargaDataCancelledTask.

¿Qué estoy haciendo mal aquí? Estoy usando y entregando la misma instancia _cancellationTokenSource.Token ... y todo lo demás (las tareas 'writingLoadedDataToGridTask' y 'loadingDataFaulted' & la siguiente tarea 'Fact.Factory.ContinueWhenAny (new [] {writeLoadedDataToGridTask, loadedDataCancelledTask, loadedDataFaulted}), => ...' bloque) trabajan realmente. Sólo cancelación no. ¿alguien ve/saber por qué?

Respuesta

8

Su continuación cancelación se está cancelando, ya que utiliza el mismo motivo de cancelación.

Si se piensa tiene sentido total: cuando dices "Quiero cancelar todo el procesamiento" en realidad obtienes lo que pides. Todo el proceso se detiene, incluida la actualización de la interfaz de usuario.

La solución es no utilizar el token de cancelación para la cancelación, el error y las continuas ContinueWhenAny. De esa forma, estas continuaciones siempre se ejecutan.

+1

oh mi, ahora que lo dices ... tiene sentido, sí. ¡¡Muchas gracias!! –

+0

Entonces, ¿qué significa 'TaskContinuationOptions.OnlyOnCanceled'? Nunca se ejecutará? – Jasper

+0

Significa que se ejecuta cuando la * tarea * base se cancela. Pero opcionalmente puede cancelar la continuación también. Si no lo desea, no le pase un token de cancelación. – usr

Cuestiones relacionadas