¿Cómo “matar” al trabajador de fondo por completo?

Estoy escribiendo una aplicación de Windows que ejecuta una secuencia de acciones digitales de E / S repetidamente.

Esta secuencia de acciones comienza cuando el usuario hace clic en un botón “INICIAR”, y lo hace un trabajador de segundo plano en backgroundWorker1_DoWork ().

Sin embargo, hay ocasiones en las que aparece el mensaje de error “Este backgroundworker está actualmente ocupado …….”.

Estoy pensando en implementar lo siguiente en el código, usando un ciclo while para “matar” al trabajador en segundo plano antes de comenzar otra secuencia de acción:

if (backgroundWorker1.IsBusy == true) { backgroundWorker1.CancelAsync(); while (backgroundWorker1.IsBusy == true) { backgroundWorker1.CancelAsync(); } backgroundWorker1.Dispose(); } backgroundWorker1.RunWorkerAsync(); 

Creo que mi principal preocupación es si eventualmente se matará al backgroundWorker1. Si lo hace, ¿llevará mucho tiempo completarlo?

¿Esta encoding me llevará a un ciclo infinito?

Puede usar algo como esto (para obtener más información sobre el aborto de subprocesos administrados y sobre ThreadAbortException, consulte ” Plumbing the Depths of ThreadAbortException Using Rotor ” de Chris Sells):

 public class AbortableBackgroundWorker : BackgroundWorker { private Thread workerThread; protected override void OnDoWork(DoWorkEventArgs e) { workerThread = Thread.CurrentThread; try { base.OnDoWork(e); } catch (ThreadAbortException) { e.Cancel = true; //We must set Cancel property to true! Thread.ResetAbort(); //Prevents ThreadAbortException propagation } } public void Abort() { if (workerThread != null) { workerThread.Abort(); workerThread = null; } } } 

Uso:

 backgroundWorker1 = new AbortableBackgroundWorker(); //... backgroundWorker1.RunWorkerAsync(); if (backgroundWorker1.IsBusy == true) { backgroundWorker1.Abort(); backgroundWorker1.Dispose(); } 

Soy de la opinión de que los hilos deberían ser responsables de sus propios recursos tanto como sea posible, incluida su propia vida.

Por lo general, es una mala idea eliminar los hilos que están fuera de su scope. Las aplicaciones que están diseñadas para pasar un mensaje a la cadena para que se cierre automáticamente tienden a tener menos problemas relacionados con el comportamiento de subprocesos múltiples.

Un subproceso debe supervisar dicho mensaje, que puede ser tan simple como un booleano establecido por otro subproceso y leído por ese subproceso de supervisión, de manera oportuna y cerrarse a sí mismo tan pronto como sea posible.

Eso significa que si debe buscar el mensaje:

  • en su bucle principal, si hay alguno.
  • periódicamente en cualquier bucle de larga ejecución.

El hilo que lo cierra con el mensaje debe esperar (pero no detener la GUI, por supuesto).

Tenga en cuenta que hay otras posibilidades para entornos con subprocesos con capacidades específicas, como el caso en que los subprocesos pueden marcarse a sí mismos cancelable a voluntad, para permitir que asesinatos externos sean más seguros.

Pero aún es más fácil simplemente diseñar tu aplicación para dejar a un maestro de hilos de su propio destino.

Puse uno que (creo) hace el trabajo. Por favor, avíseme si estoy fuera de combate. Aquí hay un simple ejemplo de cómo funciona.

 var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true}; backgroundWorker.DoWork += (sender, args) => { var thisWorker = sender as BackgroundWorker; var _child = new Thread(() => { //..Do Some Code }); _child .Start(); while (_child.IsAlive) { if (thisWorker.CancellationPending) { _child.Abort(); args.Cancel = true; } Thread.SpinWait(1); } }; backgroundWorker.RunWorkerAsync(parameter); //..Do Something... backgroundWorker.CancelAsync(); 

Como el trabajador en segundo plano es parte del grupo de subprocesos, no queremos abortarlo. Pero podemos ejecutar un hilo interno que podemos permitir que ocurra un aborto. El backgroundWorker básicamente se ejecuta hasta que el hilo hijo esté completo o le indicamos que mate el proceso. El hilo del trabajador de fondo puede regresar al grupo de lectura. Normalmente voy a resumir esto en una clase de ayuda y paso por el método de delegado que quiero que el subproceso en segundo plano se transfiera como parámetro y lo ejecute en el subproceso secundario.

Por favor, que alguien me avise si estoy golpeando mi cabeza contra la pared, pero parece que funciona bien … Pero ese es el problema con los hilos, ¿no? Los diferentes resultados que puedes obtener cuando lo ejecutas en diferentes momentos.

 public class abortableBackgroundworker: BackgroundWorker { public bool Kill = false; protected override void OnDoWork(DoWorkEventArgs e) { var _child = new Thread(() => { while (!Kill) { } e.Cancel = true;//..Do Some Code }); _child.Start(); base.OnDoWork(e); } } 

estableces kill en true para matar el hilo y no hay problema de aborto 🙂

Estaba teniendo el mismo problema, no estoy seguro si esto ayudará, pero supongo que su trabajador de segundo plano tiene un bucle dentro o saldría. Lo que tienes que hacer es poner tu lazo dentro.

Ponga dentro de su trabajador de fondo:

 while (backgroundworker1.CancellationPending == false) { //Put your code in here } 

Para matar a este trabajador de fondo, puede poner su botón:

 BackgroundWorker1.CancelAsync() 

Espero que esto ayude.