2 votes

Form.Invoke gèle l'interface utilisateur

J'ai cherché sur Google pendant environ une heure et je n'ai toujours pas trouvé de solution.

J'essaie simplement de définir la valeur maximale d'une barre de progression à partir d'un autre thread. J'ai donc trouvé la méthode Control.Invoke. J'ai commencé à l'implémenter :

Description de l'image ici

Maintenant, lorsque je débogue mon application, elle reste simplement bloquée à la ligne this.Invoke. L'interface utilisateur s'affiche, mais elle est gelée. J'ai donc continué à chercher des solutions et j'ai découvert qu'il fallait utiliser this.BeginInvoke(). Je l'ai mis en œuvre et c'était bon, l'interface utilisateur ne se figeait pas. C'est très bien, mais en fait la valeur maximale de ma barre de progression n'a pas changé :(

Qu'est-ce que je fais mal ?

EDIT : Peut-être que cela aidera : J'utilise Parallel.Invoke(); pour gérer mon thread...

5voto

Nicholas Butler Points 12630

Control.Invoke bloquera uniquement lorsqu'il est appelé sur un thread de travail et que le thread de l'interface utilisateur est bloqué.

Le code que vous avez posté est correct. Vous devez bloquer le thread de l'interface utilisateur quelque part ailleurs.

2voto

seanzi Points 833

J'utilise quelque chose de similaire ci-dessous dans mon application que j'utilise pour mettre à jour la valeur réelle de la barre de progression. Je l'ai un peu modifié par rapport à votre exemple. Essayez et voyez si cela aide :)

    public void SetMax(int value)
    {
        if (this.ProgressBar_status.InvokeRequired)
        {
           this.BeginInvoke(new Action(SetMax), value);
           return;
        }
        this.ProgressBar_status.Maximum = value;
    }

0voto

VS1 Points 3361

Je suggérerais qu'il est préférable d'utiliser le composant BackgroundWorker qui prend en charge le reporting de progrès dans la barre de progression ainsi que d'autres fonctionnalités plutôt que d'appeler invoke et BeginInvoke. Vous pouvez trouver plus de détails sur le BackgroundWorker via le lien MSDN ci-dessous:

http://msdn.microsoft.com/en-us/library/c8dcext2.aspx

0voto

Roly Points 1

J'ai eu le même problème et grâce à la réponse de Nicholas, j'ai réalisé que j'étais tombé dans le même piège dans une application GUI pour déboguer une classe utilisée dans un service Windows. La classe de service exécute la plupart de son code dans un thread. Le thread appelait une procédure de journalisation lorsqu'il s'arrêtait. Je l'arrêtais en utilisant un bouton, et la journalisation utilisait invoke pour mettre à jour un textbox. Le problème était si simple que je me suis donné un coup de pied - l'invoke attendait que le clic sur le bouton se termine, qui lui-même attendait que la classe s'arrête, qui elle-même attendait que l'invoke journalise qu'elle s'arrêtait (répéter jusqu'à ce que le gestionnaire des tâches arrête le processus). Résolu en créant un thread dans le clic sur le bouton d'arrêt, avec un procédé de thread pour arrêter la classe de service. Cela signifiait que je devais ajouter plus de code pour mettre à jour le formulaire après l'arrêt dans un autre invoke du nouveau thread, mais cela fonctionnait bien car il n'attendait pas que le thread principal du formulaire soit terminé.

0voto

8Unlimited8 Points 147

Dans mon cas, l'erreur était d'utiliser join() après le démarrage du thread. join() empêche le thread principal d'exécuter les codes avant l'achèvement du thread enfant. J'ai supprimé la commande join() et déplacé les codes après join() dans le thread et tout fonctionnait bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X