La meilleure façon de traiter avec les utilisateurs en double-cliquant sur les boutons dans une application Winforms?

StackOverflow https://stackoverflow.com/questions/255104

Question

Je travaille sur une application WinForms et je dispose d’un contrôle utilisateur. Les boutons du contrôle utilisateur déclenchent des événements jusqu'au formulaire à traiter par un autre code. L'un des boutons lance des processus qui poseront des problèmes s'ils s'exécutent simultanément. J'ai la logique dans le code pour gérer l'état de sorte qu'un utilisateur ne peut généralement pas exécuter le processus s'il est déjà en cours d'exécution. Cependant, si l'utilisateur double-clique sur le bouton, le processus sera lancé deux fois si rapidement qu'il est difficile pour moi de l'empêcher.

Je me demande quelle est la meilleure façon de gérer cela.

J'ai commencé par désactiver le bouton dans l'événement click, mais le second clic intervient avant que le premier clic ne désactive le bouton. La définition d’autres indicateurs dans le code ne l’a pas intercepté.

J'envisage d'ajouter une sorte de verrou de synchronisation sur le code qui déclenche l'événement, mais je me demande si l'un d'entre vous a une meilleure idée.

Étant donné que ce projet est presque terminé, je cherche des réponses qui n'impliquent pas une réécriture radicale de l'application (comme la mise en œuvre du bloc d'application composite). Toutefois, n'hésitez pas à poster ces idées également, car je peux les utiliser dans mes prochains projets.

Était-ce utile?

La solution

Assurez-vous que la désactivation de votre bouton ou tout autre verrouillage que vous effectuez correspond à ce que vous faites dans votre gestionnaire d’événements. Je serais extrêmement surpris si vous pouviez mettre en file d'attente deux événements de clic avant même que la première instruction ne soit déclenchée, mais je suppose que cela est possible si vous êtes sur un ordinateur très lent qui est embourbé avec d'autres applications.

Dans ce cas, utilisez un drapeau.

private bool runningExclusiveProcess = false;

public void onClickHandler(object sender, EventArgs e)
{
    if (!runningExclusiveProcess)
    {
        runningExclusiveProcess = true;
        myButton.Enabled = false;

        // Do super secret stuff here

        // If your task is synchronous, then undo your flag here:
        runningExclusiveProcess = false;
        myButton.Enabled = true;
    }
}

// Otherwise, if your task is asynchronous with a callback, then undo your flag here:
public void taskCompletedCallback()
{
    runningExclusiveProcess = false;
    myButton.Enabled = true;
}

Si vous pouvez toujours obtenir en deux clics quelque chose de ce genre, assurez-vous de ne pas être abonné accidentellement à un événement doubleClick, ou si quelque chose d'autre ne se produit pas.

Autres conseils

Traitez-vous l'événement à deux reprises?

Je suis très très surpris de lire que le second clic arrive avant que vous puissiez désactiver le bouton. Je voudrais m'assurer que vous ne participez pas deux fois à l'événement. Je l'ai fait par accident avant. Vous obtiendrez alors deux événements presque instantanément.

L'indicateur de désactivation de ce bouton ne sera pas défini tant que le gestionnaire d'événements de bouton ne sera pas terminé. Tous les clics supplémentaires seront mis en file d'attente dans la file d'attente des messages Windows après le premier clic. Assurez-vous que le gestionnaire d'événements de bouton se termine rapidement pour libérer le thread d'interface utilisateur. Il existe plusieurs façons de procéder, mais toutes impliquent de créer un thread ou de le maintenir en attente et de le préparer à un AutoResetEvent.

Par chance, est-ce que vous identifiez le bouton avec une icône? Utilisez bien sûr du code pour empêcher l'exécution de deux processus à la fois, mais vous pouvez éviter de double-cliquer du côté humain si votre bouton ressemble à un bouton de commande conventionnel (rectangulaire, étiquette de texte uniquement, surface "en relief" qui enfonce le bouton). un clic). Juste une pensée.

Désactivez le bouton dès que vous cliquez dessus. Donc, l'événement ne peut pas être géré deux fois. Dès que l'événement a été traité, vous pouvez réactiver le bouton.

La réponse cochée est proche, au mieux anecdotique. Pour les non-initiés, il manque trop de code pour avoir un sens. J'ai écrit un article sur l'utilisation des timers et des threads et l'exemple de code est VRAIMENT facile à comprendre. Essayez de le lire et de voir si vous pouvez définir les indicateurs de l'exemple ci-dessus en exécutant votre processus de tâche dans un nouveau thread:

http://www.robault.com/category/Threading.aspx

Désactivez le bouton après que l'utilisateur a cliqué dessus et avant de commencer la tâche. Une fois la tâche terminée, réactivez le bouton.

  

J'ai commencé par désactiver le bouton   dans l'événement de clic, mais le second   clic arrive avant le premier clic   provoque la désactivation du bouton.   La définition d'autres indicateurs dans le code n'a pas   attrapez-le non plus.

Étant donné que WinForms est par nature mono-thread, il ne devrait pas être possible que le second clic se déclenche avant la fin du traitement du premier (sauf si vous utilisez de nouveaux threads ou BackgroundWorkers, etc.).

Pouvez-vous nous montrer un exemple illustrant votre problème?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top