Как запустить и остановить постоянно работающий фоновый рабочий с помощью кнопки - PullRequest
6 голосов
/ 18 июня 2010

Допустим, у меня есть такой фоновый работник:

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

Как заставить этот фоновый рабочий запускать и останавливать использование кнопки на WinForm?

Ответы [ 5 ]

17 голосов
/ 18 июня 2010

Может быть, вы можете использовать подобное ручное событие, я не отлаживал это, но стоит попробовать.Если это работает, вы не будете заставлять нить вращать колеса, пока она ждет

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();
}
8 голосов
/ 18 июня 2010

Используйте метод CancelAsync .

backgroundworker1.CancelAsync();

В вашем цикле внутри рабочего потока.

if (backgroundWorker.CancellationPending) return;

Это происходит не сразу.

5 голосов
/ 18 июня 2010
4 голосов
/ 18 июня 2010

Под остановкой вы действительно подразумеваете остановку или паузу? Если вы имеете в виду стоп, то это кусок пирога. Создайте обработчик события нажатия кнопки для кнопки, за которую вы хотите отвечать за запуск фонового работника, и обработчик события нажатия кнопки для того, кто отвечает за его остановку. На вашей кнопке запуска вызовите метод фонового рабочего, который запускает событие do_work. Примерно так:

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

На вашей кнопке остановки вызовите метод, который устанавливает CancellationPending фонового работника в значение true, например:

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

Теперь не забудьте проверить флаг CancelationPending внутри DoWork вашего фонового работника. Примерно так:

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

И ваш метод doWork:

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

Я надеюсь, что это может направить вас в правильном направлении. Некоторые дальнейшие чтения:

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

0 голосов
/ 18 июня 2010

Я не проверял это, у меня где-то есть код, который мне нужно будет точно увидеть, что я сделал, но что-то вроде этого - адаптация ответа Фредрика:

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;
]

Более полный пример этого шаблона здесь:

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

...