2009-08-17 4 views
2

Ich verwende eine While-Schleife, die eine bestimmte Anzahl von Zyklen (1-576) basierend auf einem von einem Benutzer eingegebenen Wert wiederholt. Es wird aktiviert, indem der Benutzer auf einen "Start" -Knopf klickt, aber ich möchte, dass es mit der "Escape" -Taste abgebrochen werden kann.Eine While-Schleife vorzeitig abbrechen

Wenn jedoch die Schleife läuft, kann das Programm keine Tasten drücken.

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 

Meine Schleife

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

Während die Schleife meine Tastenanschläge registrieren nicht ausgeführt wird, andernfalls registrieren sie in Ordnung.

Antwort

-1

Innerhalb der Schleife den folgenden Code ein:

Application.DoEvents() 
+3

Dies ist eine schlechte Idee in .NET. Sie müssen es nicht tun, wenn Sie die BackGroundWorker-Klasse haben, mit der so einfach zu arbeiten ist, und dies kann auch zu Reentrancy-Problemen führen. -1 –

+0

Ich verstehe, dass herkömmliche Design-Praktiken in .Net dies eine schlechte Idee machen, aber in der Kontext dieser Frage ist es die richtige Antwort. Die Alternative besteht darin, ihn bei einer vollständigen Neugestaltung seiner Bewerbung zu unterstützen. Willst du dich freiwillig dafür melden? –

+0

Ich wusste nicht, dass das Hinzufügen eines BackGroundWorkers und das Refactoring einer einzelnen Methode ein "vollständiges Redesign einer (einer) Anwendung" darstellt. Das OP fragte, wie man die Benutzeroberfläche am Leben erhält, und dies ist eine schlechte (faule) Lösung. –

-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

Ich sehe nicht, wie das eine Lösung ist ... –

+0

Hate die Verwendung von Exit While, Logikblöcke sollten korrekt über die logischen Bedingungen abschließen, dh wenn counter> 10. Es kann Debugging schwierig machen, wenn der Ausgang in Code begraben ist, Im Beispiel ist es leicht zu sehen, da es nur ein paar einfache Zeilen sind, aber das ist in der Praxis normalerweise nicht der Fall. Stefan Rusek ist viel elegantere Lösung. – DaveF

5

Haben Sie daran gedacht, BackgroundWorker mit der while-Schleife Code in einem Hintergrund-Thread ausführen, making sure your GUI keeps responsive (= Größe ändern/neu gezeichnet, die Form und lassen die Benutzer "erreichen" die Art, wie Sie die Stornierung der laufenden Arbeit implementiert haben, ohne Application.DoEvents innerhalb der Schleife zu benötigen, um dieses Verhalten "vorzutäuschen"?

Wenn Sie bereits mit .NET Framework 4.0 arbeiten, können Sie versuchen, parallel programming anstelle von BackgroundWorker zu verwenden.

+0

Okay, ich habe versucht, einen BackgroundWorker-Thread zu verwenden. Ich glaube, ich habe alles eingerichtet, aber jetzt heißt es: "Cross-Thread-Operation nicht gültig: Kontrolliere 'cmb_x' von einem anderen Thread als dem Thread, auf dem er erstellt wurde." Und es scheint, dass die Lösung für DAS ist, fast meinen gesamten Code in der ursprünglichen Schleife zu ändern. – user157603

+1

Aber das ist die richtige Sache zu tun. Sie sollten verstehen, wie das Zeug funktioniert. –

+0

Haben Sie "Control.InvokeRequired" ausgecheckt? Für einige Beispiele siehe zum Beispiel http://weblogs.asp.net/justin_rogers/articles/126345.aspx. – peSHIr

2

Es gibt zwei Möglichkeiten, dies zu tun. Sie können entweder einen separaten Thread für Ihre Schleife verwenden oder Application.DoEvents() verwenden. Der Thread-Ansatz wird Ihnen im Allgemeinen die besten Ergebnisse liefern.

Threaded:

Sie rufen Sie einfach StopLoop(), um die Schleife zu sagen laufen zu stoppen. Sie möchten nicht loop = 0 setzen, da Sie dann die Interlocked-Klasse verwenden müssten, um sicherzustellen, dass die Schleife zwischen den Threads richtig eingestellt wurde.

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:

Aufruf Application.DoEvents() werden alle anstehenden Ereignisse verursachen auf das Gewinde des Fensters verarbeitet werden. Wenn jede Iteration der Schleife einige Zeit in Anspruch nimmt, wird die App dem Benutzer immer noch so angezeigt, als würde sie nicht reagieren, weshalb der Ansatz mit Threads bevorzugt wird.

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