2009-08-17 7 views
2

J'utilise une boucle While qui boucle un certain nombre de cycles (1-576) en fonction d'une valeur entrée par un utilisateur. Il est activé par l'utilisateur en cliquant sur un bouton "Démarrer", mais je voudrais qu'il puisse être annulé en utilisant, de préférence, la touche "Echap". Cependant, lorsque la boucle est en cours, le programme ne peut reconnaître aucune pression sur une touche.Annulation prématurée d'une boucle 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 

Ma boucle

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

Alors que la boucle est en cours d'exécution mes n'enregistrent pas les pressions de touche, sinon ils enregistrent bien.

Répondre

-1

l'intérieur de votre lieu de boucle le code suivant:

Application.DoEvents() 
+3

Ceci est une mauvaise idée dans .NET. Vous n'avez pas besoin de le faire quand vous avez la classe BackGroundWorker qui est si facile à utiliser, et cela peut également conduire à des problèmes de réentrance -1 –

+0

Je comprends que les pratiques de conception classiques dans .Net en font une mauvaise idée, mais dans le contexte de cette question, c'est la bonne réponse. L'alternative est de l'assister dans une refonte complète de sa demande. Vous voulez faire du bénévolat pour ça? –

+0

Je ne savais pas que l'ajout d'un BackGroundWorker et la refactorisation d'une seule méthode constituaient une "refonte complète de (une) application". Le PO a demandé comment maintenir l'interface utilisateur en vie et c'est une mauvaise solution (paresseuse). –

-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

Je ne vois pas comment c'est une solution ... –

+0

Hate l'utilisation de Exit While, les blocs logiques doivent se terminer correctement via les conditions logiques ie quand counter> 10. Cela peut rendre le débogage difficile si la sortie est enterrée dans le code, Dans l'exemple, il est facile de voir que ce n'est que quelques lignes simples, mais ce n'est généralement pas le cas en pratique. Stefan Rusek est une solution beaucoup plus élégante. – DaveF

5

Avez-vous pensé à utiliser BackgroundWorker pour exécuter le code de boucle while dans un thread d'arrière-plan, making sure your GUI keeps responsive (= redimensionnement/redessiner la forme et de laisser la utilisateur "atteindre" la façon dont vous avez mis en œuvre l'annulation du travail en cours) sans avoir besoin de Application.DoEvents à l'intérieur de la boucle pour "fausser" ce comportement? Si vous êtes déjà sur .NET Framework 4.0, vous pouvez essayer d'utiliser parallel programming au lieu de BackgroundWorker.

+0

Ok, j'ai essayé d'utiliser un thread BackgroundWorker, je crois que j'ai tout configuré, mais maintenant, il dit, "opération croisée pas valide: Contrôle 'cmb_x' accédé à partir d'un thread autre que le fil sur lequel il a été créé." Et il semble que la solution à cela est de changer presque tout mon code dans la boucle d'origine. – user157603

+1

Mais c'est la bonne chose à faire. Vous devriez comprendre comment cela fonctionne. –

+0

Avez-vous vérifié 'Control.InvokeRequired'? Voir http://weblogs.asp.net/justin_rogers/articles/126345.aspx par exemple, pour quelques exemples. – peSHIr

2

Il y a deux façons de le faire. Vous pouvez utiliser un thread séparé pour votre boucle ou utiliser Application.DoEvents(). L'approche du fil vous donnera généralement les meilleurs résultats.

fileté:

Vous appelez simplement StopLoop() pour dire la boucle d'arrêter de courir. Vous ne voulez pas définir loop = 0 car vous devrez utiliser la classe Interlocked pour vous assurer que la boucle a été correctement définie entre les threads.

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 Calling() causeront tous les événements en attente sur le fil de la fenêtre à traiter. Si chaque itération de la boucle prend du temps, alors l'application apparaîtra toujours à l'utilisateur comme si elle n'était pas réactive, c'est pourquoi l'approche par thread est préférée.

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