Sortir d’une boucle en cliquant sur un bouton – C #

J’ai une question à propos de la boucle avec événement de clic de bouton, j’ai essayé de nombreuses méthodes et cherché de nombreuses pages à la recherche d’une réponse simple au cours de la dernière heure, mais la vérité est que chaque réponse ressemble à un code étranger, probablement parce que je suis toujours très nouveau pour le développement.

Voici une version simplifiée de ce que j’essaie de faire:

private ssortingng Message = "Hello"; private void Spam(bool loop) { if(loop == true) { while (loop == true) { MessageBox.Show(Message); } } else { MessageBox.Show("Spamming has stopped !! "); } } private void button1_Click(object sender, EventArgs e) { Spam(true); } private void button2_Click(object sender, EventArgs e) { Spam(false); } 

Évidemment, ce n’est pas mon API, ou ce serait une chose inutile à inventer, cependant, le code lui-même est long et vous demandez toujours un “code pertinent” (aucun manque de respect), donc voilà.

Mon problème: sortir de la boucle de spam en cliquant sur le bouton 2, le code me semble assez correct pour que l’API puisse le comprendre, mais chaque fois que l’utilisateur clique sur le bouton 1, l’API se fige.

Utilisez un travailleur de fond pour faire votre travail. Vous pouvez utiliser la fonction d’annulation pour en sortir lorsque vous avez terminé. Votre boucle dans son état bloquera le thread d’interface utilisateur lors de son exécution synchrone, raison pour laquelle votre interface graphique ne répond plus. Notez que si vous faites une interaction avec l’interface utilisateur dans le délégué do work, vous devez réorganiser le thread d’interface utilisateur (via invoke par exemple).

 private BackgroundWorker _worker = null; private void goButton_Click(object sender, EventArgs e) { _worker = new BackgroundWorker(); _worker.WorkerSupportsCancellation = true; _worker.DoWork += new DoWorkEventHandler((state, args) => { do { if (_worker.CancellationPending) break; Console.WriteLine("Hello, world"); } while (true); }); _worker.RunWorkerAsync(); goButton.Enabled = false; stopButton.Enabled = true; } private void stopButton_Click(object sender, EventArgs e) { stopButton.Enabled = false; goButton.Enabled = true; _worker.CancelAsync(); } 

Il y a une chose importante à retenir:

Lors de l’exécution de votre code, l’utilisateur ne peut pas interagir avec votre interface utilisateur.

Cela signifie que vous devez d’abord quitter la boucle (c’est-à-dire revenir de la méthode Spam ), puis l’utilisateur peut cliquer sur Button2.

C’est une dure vérité, car cela signifie que vous ne pouvez pas écrire le code comme vous le souhaitiez. Heureusement, il existe plusieurs façons de contourner ce problème:

  • Ne pas utiliser une boucle. Utilisez une sorte de timer pour faire le “spamming”. Button1 démarre le chronomètre, Button2 l’arrête. Le type de timer disponible dépend de la bibliothèque d’interface utilisateur que vous utilisez (WinForms a une Timer , WPF a une DispatcherTimer ).

  • Faites le “spamming” dans un fil de fond . Cela permettra à votre interface utilisateur de restr sensible et vous pourrez communiquer avec le fil d’arrière-plan, par exemple, en définissant un volatile Boolean . Il s’agit toutefois d’un sujet avancé (qui peut rapidement entraîner des problèmes de synchronisation complexes). Je vous suggère donc d’essayer d’abord l’autre option.

Lorsque vous cliquez sur button1, la méthode Spam est appelée et la boucle commence. Lorsque vous cliquez sur button2, la méthode de spam est appelée, mais ce n’est pas la même chose. C’est la deuxième exécution, donc il va vérifier la condition et ne pas entrer dans la boucle, mais la boucle dans le premier appel restra active.

Vous devez utiliser un indicateur et la boucle doit utiliser cet indicateur pour déterminer si elle doit toujours être en cours d’exécution. Cela devrait ressembler à quelque chose comme ça:

 bool run = false; ssortingng message = "This API is not original"; private void Spam() { while (run == true) { MessageBox.Show(message); } } } private void button1_Click(object sender, EventArgs e) { message = "Hellooo"; flag = true; Spam(); } private void button2_Click(object sender, EventArgs e) { flag = false; } 

Jetez un oeil à ce concept:

 private bool loop = false; private void Start() { loop = true; Spam("Some Message??"); } private void Spam(ssortingng message) { while (loop) { MessageBox.Show("This API is not original"); } } private void button1_Click(object sender, EventArgs e) { loop = true; } private void button2_Click(object sender, EventArgs e) { loop = false; } 

Toutefois, l’utilisateur ne pourra pas appuyer sur un bouton si un MessageBox n’arrête pas de s’afficher lorsqu’il occupe le fil principal de l’interface utilisateur. Pour éviter cela, vous pouvez utiliser BackgroundWorker ou créer un nouveau thread.