Скажем, у меня есть второстепенный рабочий как это:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
//Kill zombies
}
}
Как я могу заставить этого второстепенного рабочего запустить и прекратить использовать кнопку на WinForm?
Под остановкой вы действительно имеете в виду остановку или паузу? Если вы имеете в виду стоп, то это проще простого. Создайте обработчик события нажатия кнопки для кнопки, которую вы хотите нести ответственность за запуск фонового работника, и обработчик события нажатия кнопки для того, кто отвечает за его остановку. На кнопке запуска вызовите метод фонового рабочего, который запускает событие 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/ библиотека / system.componentmodel.backgroundworker.aspx
Я не тестировал это, у меня где-то есть код, надо будет посмотреть, что именно я сделал, но что-то вроде этого - адаптация ответа Фредрика:
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;
]
Более полный пример этого паттерна здесь:
Используйте метод CancelAsync .
backgroundworker1.CancelAsync();
В вашем цикле внутри рабочего потока.
if (backgroundWorker.CancellationPending) return;
Это происходит не сразу.
Может быть, вы можете использовать подобное ручное событие, я не отлаживал это, но попробовать стоит. Если это сработает, вы не будете заставлять поток крутиться в ожидании
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();
}