2009-08-17 3 views
2

Я использую цикл While, который зацикливает определенное количество циклов (1-576) на основе значения, введенного пользователем. Он активируется пользователем, нажимая кнопку «Пуск», но я бы хотел, чтобы он мог быть отменен с использованием, предпочтительно, клавиши «Escape».Преждевременное отключение цикла While

Однако, когда цикл идет, я не могу заставить программу распознавать любые нажатия клавиш.

Private Sub OnGlobalKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles kh.KeyDown 

     lblInput.Text = String.Format("'{0}' Code:{1}", e.KeyCode, CInt(e.KeyCode).ToString()) 


     If e.KeyCode = CType(27, Keys) Then 
        count = 0 
        loops = 0 
     End If 
    End Sub 

My Loop

Private Sub RUNLOOP() 
      While loops >= 1 
        ' my code that runs in the loop 
        loop = loop - 1 
      End While 
End Sub 

В то время как цикл выполняется мои нажатия клавиш не регистрируются, в противном случае они регистрируются в порядке.

ответ

-1

Внутри вашего места петли следующий код:

Application.DoEvents() 
+3

Это плохая идея в .NET. Вам не нужно это делать, когда у вас есть класс BackGroundWorker, с которым так легко работать, и это также может привести к проблемам с повторным подключением. -1 –

+0

Я понимаю, что обычные методы проектирования в .NET делают это плохой идеей, но в контекст этого вопроса, это правильный ответ. Альтернатива заключается в том, чтобы помочь ему в полной редизайне его заявления. Вы хотите добровольно участвовать в этом? –

+0

Я не знал, что добавление BackGroundWorker и рефакторинг одного метода представляет собой «полную редизайн приложения». ОП задал вопрос о том, как сохранить пользовательский интерфейс живым, и это плохое (ленивое) решение. –

-3
While counter <= 10 
     ' skip remaining code in loop only if counter = 7 
     If counter = 7 Then 
      Exit While 
     End If 

     counter += 1 
     End While 
+0

Я не вижу, как это решение ... –

+0

Ненавидеть использование выхода. В то время как логические блоки должны корректно выполняться через логические условия, т. Е. Когда счетчик> 10. Он может сделать отладку сложной, если выход похож на код, в примере это легко увидеть, потому что это всего лишь пара простых строк, но на практике это обычно не так. Stefan Rusek - гораздо более элегантное решение. – DaveF

5

Задумывались ли вы с помощью BackgroundWorker для выполнения кода время цикла в фоновом потоке, making sure your GUI keeps responsive (= изменение размера/перерисовки формы и позволяя пользователь «достигает» того, как вы реализовали отмену выполняемой работы), не нуждаясь в Application.DoEvents внутри цикла, чтобы «подделать» это поведение?

Если вы уже используете .NET Framework 4.0, вы можете попробовать использовать parallel programming вместо BackgroundWorker.

+0

Хорошо, я попытался использовать поток BackgroundWorker, я считаю, что у меня все настроено, но теперь он говорит: «Неверная операция поперечного потока: Control 'cmb_x' обращается к потоку, отличному от потока, в котором он был создан." И кажется, что решение THAT заключается в том, чтобы изменить почти весь мой код в исходном цикле. – user157603

+1

Но это правильная вещь. Вы должны понимать, как это работает. –

+0

Вы проверили 'Control.InvokeRequired'? Например, для некоторых примеров см. Http://weblogs.asp.net/justin_rogers/articles/126345.aspx. – peSHIr

2

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

Каскадный:

Вы просто позвоните StopLoop(), чтобы сказать цикл, чтобы остановить выполнение. Вы не хотите устанавливать loop = 0, потому что тогда вам придется использовать класс Interlocked, чтобы гарантировать, что цикл был установлен правильно между потоками.

Private Sub RunLoop() 
    Dim loop As Action = AddressOf InternalRunLoop 
    loop.BeginInvoke(null, null) 
End Sub 

Private bStopLoop As Boolean 

Private Sub InternalRunLoop() 
    While loops >= 1 And Not bStopLoop 
    ' my code that runs in the loop 
    loop = loop - 1 
    End While 
End Sub 

Private Sub StopLoop() 
    bStopLoop = True 
End Sub 

DoEvents:

Вызывающие Application.DoEvents() будет вызывать все ожидающие события на нити окна должны быть обработаны. Если каждая итерация цикла занимает некоторое время, приложение все равно будет отображаться для пользователя, как будто оно не реагирует, поэтому предпочтительным является многопоточный подход.

Private SubRunLoop() 
    While loops >= 1 And Not bStopLoop 
    ' my code that runs in the loop 
    loop = loop - 1 
    Application.DoEvents() 
    End While 
End Sub 
Смежные вопросы