2010-07-15 19 views
5

Tengo UI que muestra el estado de las operaciones de larga ejecución (descarga algunos archivos de texto de ftp). Para mis propósitos, uso backgroundworker y no puedo cancelar la operación.Cancelar backgroundworker

void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 

     try 
     { 
      int rowIndex = (int)e.Argument; 

      //begin UI update 
      StartWaitingBar(rowIndex); 
      //get provider id cell 
      GridViewDataRowInfo row = _proivderGridView.Rows[rowIndex]; 
      GridViewCellInfo provIdCell = row.Cells[ "ProviderId" ]; 

      var providerData = GetProviderData(Convert.ToInt32(provIdCell.Value)); 
      var provider = ProviderFactory.CreateProvider(providerData); 
      provider.Synchronize(); 
      e.Result = rowIndex; 

     } 
     catch (Exception exception) 
     { 
      return; 
     } 
    } 

Y el código para la creación del trabajador:

  BackgroundWorker worker = new BackgroundWorker(); 
      worker.DoWork += worker_DoWork; 
      worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
      worker.WorkerSupportsCancellation = true; 
      worker.RunWorkerAsync(args.RowIndex); 
      _syncWorkers.Add(providerId,worker); 
      ... 
      var worker = _syncWorkers[providerId]; 

      if(worker.IsBusy) 
      { 
       worker.CancelAsync(); 
      } 
      else 
      { 
       worker.RunWorkerAsync(args.RowIndex); 
      } 

solución proporcionada here no parece estar funcionando para mí por culpa funciona para las operaciones recurrentes (por la que se crea trabajador de fondo, supongo). ¿Debo usar hilos (abortar y unirme) para mis propósitos porque debería proporcionar posibilidades para que el usuario cancele la operación de larga ejecución?

Necesitas tu consejo.

Gracias de antemano.

Respuesta

7

No puede utilizar Backgroundworker.CancelAsync() para cancelar una carrera de larga acción de E/S. Al igual que rifnl respondió, DoWork tiene que marcar worker.CancellationPending y establecer e.Cancel.

Pero tampoco debe usar Thread.Abort(). Podría desestabilizar tu proceso.

La solución que necesita tiene que venir de provider.Synchronize(); de alguna manera.

PD: y catch { return; } es horrible. Elimine todo el try/catch y deje que Bgw maneje las excepciones.

+0

Alternativamente, si es posible dar el valor Sincronizar a TimeOut, puede poner la sincronización en mientras (! E.CancellationPending) privider.Synchronize (TimeOut); // si es posible loop, mientras continúa la función que tiene actualmente. – greggorob64

2

Debe verificar e.Cancelar dentro de su método DoWork, que falta en su fragmento de código, pero también debe cambiar su método de descarga a una llamada asíncrona, está llamando al método y espera la respuesta dentro del dowork. Lo cual es posible, pero no verificará la bandera de cancelación en el tiempo medio.

Comprobar la solución informados (línea 3):

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(!e.Cancel) 
    { 
     // do something 
    } 

    _resetEvent.Set(); // signal that worker is done 
} 
+0

¡Gracias por la respuesta! Entiendo tu punto, pero ¿tengo que usar Backgraound Worker para nada? Puedo usar la operación asincrónica (como lo hice inicialmente) y usar AutoResetEvent para lograr la cancelación ... – Sharov

+0

Como dijo riffnl, 'BackgroundWorker' no admite la cancelación. No tiene que usar 'BackgroundWorker', pero le recomiendo mover * arriba * en abstracción a' Tarea', en lugar de * abajo * en abstracción a delegados asincrónicos. –

+0

@rifnl, no es e.Cancel. –

Cuestiones relacionadas