2011-04-07 7 views
3

Devrait être simple, mais ... :)Désactiver temporairement le bouton

Je n'ai qu'un bouton sur le formulaire. Le bouton appelle une fonction, qui prend 10 secondes à exécuter (par exemple). Je voudrais désactiver temporairement le bouton pendant ce temps, de sorte que si l'utilisateur appuie sur la touche Entrée pendant que la fonction est en cours d'exécution, rien ne se passera.

Mais maintenant cela fonctionne de cette façon: l'utilisateur appuie sur Entrée et le bouton est désactivé. Pendant ces 10 secondes, l'utilisateur appuie à nouveau sur la touche Entrée et lorsque la première fonction se termine, elle est à nouveau appelée. Je voudrais empêcher cela, de sorte que la touche Entrée ne fonctionne que lorsque le bouton est à nouveau activé. Tout est dans le même fil.

Mon code:

private void button1_Click(object sender, EventArgs e) 
{ 
    Debug.WriteLine("Click"); 
    button1.Enabled = false; 
    Thread.Sleep(3000); // simulate something... 
    button1.Enabled = true; 
    button1.Focus(); 
} 

Edit: la fonction imprime quelque chose sur l'imprimante. Grâce à la fonction API d'une imprimante, je peux déterminer quand l'impression a été terminée, seulement alors le bouton peut être activé à nouveau.

+0

avez-vous essayé ** this.AcceptButton = null ** et après avoir terminé ensemble ** this.AcceptButton = button1 ** en plus de basculer ** Enabled ** – V4Vendetta

+0

Que fait la fonction? – jfs

+0

@ V4Vendetta - aucune différence. – sventevit

Répondre

1

Si vous savez que l'opération à exécuter prendra plus de temps (par exemple> 5 secondes), il peut être préférable d'effectuer cette action de manière asynchrone. Dans ce cas, prenez un BackgroundWorker. Vous pouvez facilement désactiver le bouton avant de démarrer BackgroundWorker et l'activer de nouveau dans son événement Terminé.

+0

Fonctionne très bien, merci. Je me demande si cela peut être fait dans le même fil. – sventevit

0

Essayez ce code.

AutoResetEvent _autoResetEvent = new AutoResetEvent(false); 

private button1_click(object o, EventArgs e) 
{ 
    button1.Enabled = false; 
    DoPrinterJob(); 
    button1.Enabled = _autoResetEvent.WaitOne(); 
} 

private void DoPrinterJob() 
{ 
    //Do something. 
    _autoResetEvent.Set(); 
} 

Espérons que cela aide.

+1

cela ne fonctionnera pas.L'interface graphique est toujours bloquée dans l'appel WaitOne() et ne traitera pas les événements. Les clics s'accumuleront et, la prochaine fois qu'ils les traiteront, la propriété enabled du bouton sera vraie et le gestionnaire exécutera –

3

J'ai eu le même problème récemment et j'ai décidé de poster mon explication:

La tâche longue est en cours d'exécution, l'utilisateur clique plusieurs fois sur le bouton. Windows envoie ces messages à l'application, mais l'application ne peut pas les traiter immédiatement puisqu'elle est occupée en ce moment. Ainsi, les messages attendent dans une file d'attente pour que l'application devienne disponible. Lorsque l'application se termine avec la tâche, la propriété Enabled du bouton est immédiatement définie sur True et la prochaine étape est, il reçoit les messages en file d'attente. À ce moment, le bouton est activé pour que l'application traite les nouveaux clics comme si le bouton n'était jamais désactivé.

Fix proposition:

Vous pouvez insérer la ligne "Application.DoEvents()" juste avant la ligne "button1.Enabled = true;" De cette façon, les messages en file d'attente atteindront le bouton alors qu'il est encore désactivé et le bouton va maintenant les ignorer.

Clause de non-responsabilité: Il semble que l'utilisation de Application.DoEvents() ne soit pas considérée comme une bonne pratique. Cependant, cela montre bien ce qui se passe dans ce cas particulier.

Je pense que la solution suggérée par Rhapsody est meilleure que d'utiliser Application.DoEvents(). Avec BackgroundWorker nous créons un deuxième thread et donc nous ne bloquons pas le thread graphique. Comme l'interface graphique reste réactive, la désactivation du bouton fonctionnera comme prévu.

+0

C'est exactement ce qui se passait pour moi et DoEvents a résolu le problème. Je ne suis pas bon avec winforms donc je ne comprends pas pourquoi le travail suggéré par Rhapsody fonctionne parce que le problème n'est pas en désactivant et en activant le bouton mais dans les messages mis en file d'attente et agi dès que le bouton est activé? –

+0

@Shaikh Owais: En fait, je dirais que Application.DoEvents() est la solution de contournement ici. Voir ma modification. –

Questions connexes