2011-02-14 28 views
8

Necesita ayuda para detener el subproceso BackgroundWorker. Estoy tratando de detener un hilo de trabajador de fondo. Esto es lo que estoy haciendo:Necesita ayuda para detener el subproceso BackgroundWorker

El botón de parada de clic (capa de interfaz de usuario):

if (backgroundWorker.IsBusy == true && 
    backgroundWorker.WorkerSupportsCancellation == true) 
{ 
    backgroundWorker.CancelAsync(); 
} 

En caso DoWork (capa de interfaz de usuario):

if ((backgroundWorker.CancellationPending == true)) 
{ 
    e.Cancel = true; 
} 
else 
{ 
    //Function which progresses the progress bar is called 
    //here with its definition in business layer 
} 

Una vez que el evento DoWork se dispara y mi el control del programa está en la función definida en la capa empresarial, ¿cómo puedo volver al evento DoWork para establecer 'e.Cancel = true'?

Respuesta

2

DoWork se ejecutará en su propio hilo y no depende del hilo de la GUI.

Hace casi todo lo correcto. Desde el hilo de la GUI, configure CancellationPending en true.

En el método DoWork, es probable que tenga un bucle de algún tipo.

Aquí puede comprobar si CancellationPending == true, pero además de establecer e.Cancel en true, también incluya una llamada return para hacer que el método regrese y detener efectivamente al trabajador. Esto también hace que el evento WorkerCompleted se active en el hilo de GUI si el método está conectado.

Si el método DoWork realizar alguna tarea larga que no se divide en partes (por ejemplo, si su método de DoWork se parece a esto:

void DoWork((object sender, DoWorkEventArgs e) 
{ 
    myClass.SomeLongOperation(); 
} 

Entonces estás de suerte, ya que se necesita para comprobar manualmente el CancellationPending dentro del método DoWork para poder detenerlo. Si el DoWork en sí "cuelga" y espera una operación que no puede controlar, no puede detenerlo (de forma ordenada) configurando CancellationPending desde la GUI hilo

+1

.. Y si> no stuartd

+1

@ Stuart - Eso es correcto, como se menciona en la respuesta. Si no hay ningún bucle, no hay una buena manera de apagarlo sin matar forzosamente el hilo de la secuencia de la GUI. –

+0

@ Øyvind Knobloch-Bråthen - Por favor dígame cuál es la MALA manera de matar a la fuerza el hilo de Backgroundworker del hilo de la interfaz gráfica de usuario. (sin bucle en DoWork) – Zeeshanef

3

Configuración de e.Cancel no hace nada, si CancellationPending es cierto, básicamente tiene que salir de DoWork() usando return o lo que sea (después de haber detenido lo que está haciendo).

Algo así como:

private void DoWork(...) 
{ 
    // An infinite loop of work! 
    while (true) 
    { 
     // If set to cancel, break the loop 
     if (worker.CancellationPending) 
      break; 

     // Sleep for a bit (do work) 
     Thread.Sleep(100); 
    } 
} 

DoWork() se ejecuta en un hilo separado para el hilo de interfaz de usuario, puede informar al hilo de interfaz de usuario mediante BackgroundWorkr.ReportProgress().

0

Siga comprobando el CancelPending = True Flag en la parte else de su lógica y devuélvalo cuando sea verdadero.

2

Una vez que se activa el evento DoWork y mi control de programa está en la función definida en Business layer, ¿cómo puedo volver al evento DoWork para establecer 'e.Cancel = true'?

Usted no lo hace. Si desea que la cancelación sea posible durante la ejecución de su capa de negocio, entonces su capa de negocio debe admitir la cancelación.Entonces, tiene dos opciones:

  1. En su método DoWork, llame solo a los métodos de capa de negocios de corta duración y compruebe la CancelaciónPending en el medio.
  2. Haga que sus métodos de capa empresarial sean conscientes de la cancelación, es decir, páseles el BackgroundWorker y pídales que comprueben CancelPending periódicamente (y lo vuelvan a hacer, una vez que se vuelva verdadero).
0

El código e.Cancel = true solo establece un estado en el BackgroundWorker, por lo que sabe que se ha cancelado, en realidad no cancela el proceso.

Deberá verificar el CancellationPending dentro del ciclo de su método y break o return.

void DoWork(object sender, DoWorkEventArgs e) { 
    for (int i = 0; i < length; i++) { 
     if(e.CancellationPending) { 
      return; 
     } 
     // Long running code 
    } 
} 
Cuestiones relacionadas