остановка функции, выполняемой по нажатию кнопки winform - PullRequest
2 голосов
/ 03 ноября 2008
  1. В простом приложении winform я вызываю функцию, которая бесконечно создает файлы при нажатии кнопки. Я добавляю Application.DoEvents () в цикл.

  2. Я нажимаю красную кнопку X, чтобы закрыть форму.

  3. форма закрывается, но файлы продолжают создаваться ...

Я думаю, что это на кнопке темы, но не должно ли это быть фоновым? Попытка изменить Thread.CurrentThread.IsBackGround на True в функции цикла не помогает.

Идеи?

Ответы [ 5 ]

5 голосов
/ 03 ноября 2008

Тот факт, что вы используете Application.DoEvents, является первым признаком проблемы: он показывает, что вы слишком много делаете в потоке пользовательского интерфейса. Это почти никогда не подходит в хорошо структурированной программе. Поток пользовательского интерфейса не предназначен для выполнения длительных задач. (Следует признать, что если рисование вашего пользовательского интерфейса занимает много времени, у вас мало выбора - но это предполагает, что вы должны упростить свой пользовательский интерфейс ... и я подозреваю, что это не применимо в этом случае.)

Вместо этого вы должны выполнять долгосрочную задачу (создание файлов) в отдельном потоке. BackgroundWorker идеально подходит для этого - вы можете использовать его, чтобы сообщить о прогрессе обратно в пользовательский интерфейс, и пользовательский интерфейс может вызвать CancelAsync метод, чтобы запросить его остановку. Вам нужно проверить свойство CancellationPending в рабочем потоке, чтобы узнать, была ли запрошена отмена, и правильно остановиться.

РЕДАКТИРОВАТЬ: Просто чтобы прояснить, что, по моему мнению, происходит - я подозреваю, что ваша форма закрывается, но программа не завершит работу, пока цикл событий не завершится. Вы продолжаете цикл событий вместе с циклом создания файла, поэтому проблема.

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

2 голосов
/ 03 ноября 2008

Добавьте эту переменную уровня формы к коду вашей формы:

private bool _StillOpen = true;

Затем оберните код бесконечной петли в вашем нажатии кнопки следующим образом:

while (_StillOpen)
{
    // do whatever your method does
    Application.DoEvents();
}

Наконец, добавьте этот код в событие FormClosing вашей формы:

_StillOpen = false;

Это позволит закрывать форму при нажатии кнопки закрытия. В идеале вы хотели бы, чтобы что-то подобное выполнялось в фоновом потоке, но такой подход с использованием флагов может быстро решить вашу текущую проблему.

1 голос
/ 03 ноября 2008

Обработчик нажатия кнопки выполняется в потоке пользовательского интерфейса.

Когда вы вызываете Application.DoEvents, вы позволяете потоку пользовательского интерфейса обрабатывать сообщения окна. Одним из последствий этого является то, что каждый раз, когда пользователь нажимает эту кнопку, в стек добавляется новый «экземпляр» (фрейм стека) метода обработчика кликов вместе со многими другими фреймами стека. Как это:

{windows forms methods incl. message pump}
  **ClickHandler**
    Application.DoEvents
     {windows forms methods incl. message pump}
      **ClickHandler**
       Application.DoEvents
        {windows forms methods incl. message pump}
          etc.

Это все довольно ужасно.

Если вы хотите запустить код в фоновом режиме, лучше использовать

  • Компонент BackgroundWorker.
  • Стандартный механизм на основе делегатов .NET (BeginInvoke, EndInvoke, IAsyncResult и т. Д.) Для запуска кода в пуле потоков.
  • Если вы хотите реализовать длительный фоновый поток, а не выделять «пул работ» в пул, вы можете создать и запустить поток, который настроен как фоновый поток.
0 голосов
/ 03 ноября 2008

Вы пытались позвонить Thread.CurrentThread.Abort()? Это не рекомендуемый способ, но если у вас нет доступа к функции s source code it might help (even though you say you are calling DoEvents` из функции).

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

Кроме того, вы можете использовать компонент background worker или создать другой поток и управлять им извне (то есть из формы)

0 голосов
/ 03 ноября 2008

Вы специально создали новый поток для этого кода ButtonClick? Если нет, то он находится в том же потоке, что и форма, поэтому кнопка «X» должна остановить его.

В любом случае вы можете установить флаг (isClosing) и проверить этот флаг в цикле «while true».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...