Cómo iniciar y detener un trabajador de fondo en ejecución continua utilizando un botón

Digamos que tengo un trabajador de fondo como este:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while(true) { //Kill zombies } } 

¿Cómo puedo hacer que este trabajador de fondo comience y deje de usar un botón en un WinForm?

Así es como hacerlo (enlace para responder abajo)

Tal vez puedas usar un dispositivo manual como este, no lo he corregido, pero vale la pena intentarlo. Si funciona, no tendrás el hilo girando sus ruedas mientras está esperando.

 ManualResetEvent run = new ManualResetEvent(true); private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while(run.WaitOne()) { //Kill zombies } } private void War() { run.Set(); } private void Peace() { run.Reset(); } 

Utilice el método CancelAsync .

 backgroundworker1.CancelAsync(); 

En su bucle dentro del hilo trabajador.

 if (backgroundWorker.CancellationPending) return; 

Esto no sucede de inmediato.

Por parada, ¿realmente quiere decir parar o quiere decir pausa? Si te refieres a parar, entonces esto es un pedazo de pastel. Cree un controlador de eventos de clic de botón para el botón que desea que sea responsable de iniciar el trabajador de fondo y un controlador de eventos de clic de botón para el responsable de detenerlo. En el botón de inicio, realice una llamada al método de trabajo en segundo plano que activa el evento do_work. Algo como esto:

 private void startButton_Click(System.Object sender, System.EventArgs e) { // Start the asynchronous operation. backgroundWorker1.RunWorkerAsync(); } 

En su botón de parada, realice una llamada al método que establece la CancellationPending pendiente del trabajador de fondo en verdadero, como esto:

 private void cancelAsyncButton_Click(System.Object sender, System.EventArgs e) { // Cancel the asynchronous operation. this.backgroundWorker1.CancelAsync(); } 

Ahora no se olvide de verificar la CancelationPending en el trabajo de su trabajador de fondo. Algo como esto:

  private void KillZombies(BackgroundWorker worker, DoWorkEventArgs e) { while (true) { if (worker.CancellationPending) { e.Cancel = true; } } } 

Y tu método de trabajo:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; KillZombies(worker, e); } 

Espero que esto pueda guiarte en la dirección correcta. Algunas lecturas adicionales:

http://msdn.microsoft.com/en-us/library/b2zk6580(v=VS.90).aspx

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

http://msdn.microsoft.com/en-us/library/waw3xexc.aspx

No he probado esto, tengo un código en algún lugar donde tendré que ver exactamente lo que hice, pero algo como esto es una adaptación de la respuesta de Fredrik:

 private bool _performKilling; private object _lockObject = new object(); private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while(true) { if (_performKilling) { //Kill zombies } else { //We pause until we are woken up so as not to consume cycles Monitor.Wait(_lockObject); } } } private void StartKilling() { _performKilling = true; Monitor.Pulse(_lockObject); } private void StopAllThatKilling() { _performKilling = false; ] 

Un ejemplo más completo de este patrón aquí:

https://github.com/AaronLS/CellularAutomataAsNeuralNetwork/blob/fe9e6b950e5e28d2c99350cb8ff3157720555e14/CellLifeGame1/Modeling.cs