2 votes

Appeler les contrôles de formulaires Windows en toute sécurité

L'article de MSDN : Comment faire : Effectuer des appels sécurisés pour les contrôles Windows Forms dit que nous devrions utiliser un délégué asynchrone pour faire l'appel. Mais pourquoi le délégué asynchrone rend-il l'appel sûr ?

2voto

Sergey Teplyakov Points 6556

Les contrôles Windows utilisent le modèle d'appartement unique (STA) du Component Object Model (COM) parce que ces contrôles sous-jacents sont des appartements-threads. En outre, de nombreux contrôles utilisent la pompe à messages pour de nombreuses opérations. Ce modèle stipule que tous les appels de fonction à chaque contrôle doivent se faire sur le même thread qui a créé le contrôle. Invoke (et BeginInvoke et EndInvoke) achemine les appels de méthode vers le bon thread.

Extrait de More Effective C# de Bill Wagner. Point 16. Comprendre les appels inter-filières dans Windows Forms et WPF

1voto

Anonym Points 167

Vous appellerez control.BeginInvoke() ou control.Invoke() et cette méthode se chargera d'insérer votre délégué dans le thread de distribution de l'interface graphique en toute sécurité, de sorte que, un peu plus tard, votre délégué sera traité et exécuté dans le thread de l'interface graphique et non dans le thread dans lequel vous vous trouvez.

1voto

Gishu Points 59012

L'essentiel est là : Vous ne devriez pas mettre à jour les contrôles de l'interface utilisateur à partir d'un thread autre que celui sur lequel le contrôle a été créé (UI / Main Thread). Sinon, vous risquez d'observer des comportements imprévisibles.

Si vous devez mettre à jour l'interface utilisateur à partir d'un fil de travail (autre que le fil principal), vous devez revenir au fil d'interface utilisateur avant de mettre à jour l'interface utilisateur.

L'article suggère d'utiliser

  • IsInvokeRequired (qui renvoie vrai si le thread actuel n'est pas celui dans lequel l'interface utilisateur a été créée) et Invoke(delegate) qui exécute le délégué sur le thread correct/UI. Ceci est utile lorsque vous voulez mettre à jour l'interface utilisateur. entre les deux le processus asynchrone. Par exemple, mettre à jour la progression sur l'interface utilisateur.

  • BackgroundWorker qui exécute les gestionnaires enregistrés pour son DoWork asynchrone sur un fil de travail et exécute les gestionnaires enregistrés pour son événement. RunWorkerCompleted sur le thread appelant. C'est l'idéal si vous voulez mettre à jour l'interface utilisateur avec quelque chose après la tâche asynchrone est terminée, par exemple en affichant une indication "Done" sur l'interface utilisateur.

0voto

n535 Points 2558

En effet, les contrôles des formulaires Windows sont conçus de cette manière, de sorte qu'on ne peut y accéder qu'à l'intérieur du fil de discussion qui leur appartient. Et le délégué asynchrone, lorsqu'il est utilisé correctement, rend l'appel sûr.

La réponse à la question posée est contenue dans le deuxième paragraphe de l'article MSDN donné =)

L'accès aux contrôles Windows Forms n'est pas intrinsèquement sûr pour les threads. Si deux threads ou plus manipulent l'état d'un contrôle, il est possible de forcer le contrôle dans un état incohérent. D'autres bogues liés aux threads sont possibles, tels que des conditions de course et des blocages. Il est important de s'assurer que l'accès à vos contrôles est effectué de manière sûre pour les threads.

Vous devez vérifier si vous pouvez accéder au contrôle immédiatement, sans indirection (en vérifiant la propriété InvokeRequired), si vous ne pouvez pas, vous devez y accéder de manière asynchrone (explication très simplifiée : le système attendra jusqu'à ce qu'il puisse accéder à un contrôle en toute sécurité).

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