C # вырваться из цикла при нажатии кнопки

2

У меня простой цикл С# foreach, как я могу вырваться из цикла при нажатии кнопки? Это не в фоновом режиме, поэтому я не могу использовать backgroundWorker.CancellationPending.

  • 1
    Используется ли цикл foreach в отдельном потоке? или в потоке пользовательского интерфейса?
  • 0
    Работает ли цикл в другом потоке?
Показать ещё 3 комментария
Теги:
foreach

3 ответа

5
Лучший ответ

Создайте в форме булевский флаг. Прикрепите обработчик события к событию щелчка кнопок и установите флаг в true в обработчике событий.

Проверьте флаг в цикле, и если это правда, вызовите "break". (Лучшим вариантом было бы использовать цикл while вместо цикла for с проверкой флага в состоянии while)

Очевидно, цикл for должен быть в какой-то форме фонового потока, иначе GUI не будет реагировать. Если вы не знаете, как это сделать, проверьте ThreadPool.QueueUserWorkItem или BackgroundWorker. Если вы используете BackgroundWorker, вы можете использовать встроенный метод CancelAsync() вместо того, чтобы кодировать свой собственный флаг отмены.

[Edit: Как указано другими (ниже) и более подробно обсуждены здесь и здесь; вам нужно либо заблокировать до доступа к bool, либо пометить его как volatile]

[Не забудьте установить правильное состояние флага перед запуском цикла.]

  • 4
    Очевидно, что флаг должен быть изменчивым, или доступ должен быть синхронизирован.
  • 3
    efraim, зачем вам нужно синхронизировать доступ к простому bool-полю? Пользователь не может очень хорошо нажать кнопку, которая запускает цикл И кнопку, которая одновременно ее отменяет, не так ли?
Показать ещё 8 комментариев
4

Вот не очень хорошее решение.

Вызовите Application.DoEvents() на каждой итерации свой цикл. В Button-Click установите переменную в True и в цикле проверьте эту переменную. Если это так, продолжайте разрыв в противном случае.

Как я уже сказал, это не очень хорошее решение. Application.DoEvents() может быть очень опасным. Лучший вариант здесь - создать фоновый поток.

  • 2
    Я согласен. Это не очень хорошее решение. Не используйте DoEvents. Поместите цикл for в фоновый поток, используя фоновый рабочий или ThreadPool.QueueUserWorkItem ().
  • 0
    +1 для чего-то, что действительно работает, даже если это довольно уродливое решение, которое не масштабируется ... Вы можете добавить к нему счетчик и вызывать DoEvents каждую n-ю итерацию, чтобы уменьшить снижение производительности.
0

Вы можете использовать DoEvents, как предложил Аамир, в качестве быстрого исправления.

Для более масштабируемого и поддерживаемого решения вам нужно переместить работу в отдельный поток. Тогда довольно тривиально, чтобы событие нажатия кнопки установило флаг, чтобы остановить цикл. С другой стороны, есть немного больше работы для передачи результата обратно в поток пользовательского интерфейса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню