Quelqu'un peut-il s'il vous plaît expliquer cette déclaration écrite sur ce lien
Invoke(Delegate):
Exécute le délégué spécifié sur le thread qui possède le handle de fenêtre sous-jacent du contrôle.
Quelqu'un peut-il expliquer ce que cela signifie (en particulier le gras) Je ne suis pas en mesure de le comprendre clairement
Réponses:
La réponse à cette question réside dans le fonctionnement des contrôles C #
De Control.InvokeRequired
En fait, ce que fait Invoke est de s'assurer que le code que vous appelez se produit sur le thread sur lequel le contrôle «vit», empêchant efficacement les exceptions entre threads.
D'un point de vue historique, dans .Net 1.1, cela était en fait autorisé. Cela signifiait que vous pouviez essayer d'exécuter du code sur le thread "GUI" à partir de n'importe quel thread d'arrière-plan et cela fonctionnerait principalement. Parfois, cela provoquait simplement la fermeture de votre application parce que vous interrompiez effectivement le thread GUI pendant qu'il faisait autre chose. Il s'agit de l' exception de threads croisés - imaginez que vous essayez de mettre à jour une zone de texte pendant que l'interface graphique peint autre chose.
En effet, vous interrompez une file d'attente, ce qui peut avoir de nombreuses conséquences imprévues. Invoke est en fait le moyen «poli» d'obtenir ce que vous voulez faire dans cette file d'attente, et cette règle a été appliquée à partir de .Net 2.0 via une exception InvalidOperationException. .
Pour comprendre ce qui se passe réellement dans les coulisses, et ce que l'on entend par "fil GUI", il est utile de comprendre ce qu'est une pompe de message ou une boucle de message.
Ceci est en fait déjà répondu à la question " Qu'est-ce qu'une pompe à messages " et il est recommandé de le lire pour comprendre le mécanisme réel auquel vous vous connectez lorsque vous interagissez avec les contrôles.
D'autres lectures que vous pourriez trouver utiles incluent:
Quoi de neuf avec Begin Invoke
et, pour un aperçu plus lourd du code avec un échantillon représentatif:
Opérations cross-thread non valides
Une fois que vous aurez compris InvokeRequired, vous souhaiterez peut-être envisager d'utiliser une méthode d'extension pour encapsuler ces appels. Ceci est bien couvert dans la question de débordement de pile Nettoyage du code jonché avec Invoke requis .
Il y a aussi un autre article sur ce qui s'est passé historiquement qui peut être intéressant.
la source
Un objet de contrôle ou de fenêtre dans Windows Forms est juste un wrapper autour d'une fenêtre Win32 identifiée par un handle (parfois appelé HWND). La plupart des opérations que vous effectuez avec le contrôle aboutiront finalement à un appel d'API Win32 qui utilise ce handle. Le handle appartient au thread qui l'a créé (généralement le thread principal) et ne doit pas être manipulé par un autre thread. Si, pour une raison quelconque, vous devez faire quelque chose avec le contrôle d'un autre thread, vous pouvez utiliser
Invoke
pour demander au thread principal de le faire en votre nom.Par exemple, si vous souhaitez modifier le texte d'une étiquette à partir d'un thread de travail, vous pouvez faire quelque chose comme ceci:
la source
this.Invoke(() => this.Enabled = true);
Tout cethis
à quoi se réfère est sûrement dans le fil actuel, non?Si vous souhaitez modifier un contrôle, cela doit être fait dans le thread dans lequel le contrôle a été créé. Cette
Invoke
méthode vous permet d'exécuter des méthodes dans le thread associé (le thread qui possède le handle de fenêtre sous-jacent du contrôle).Dans l'exemple ci-dessous, thread1 lève une exception car SetText1 tente de modifier textBox1.Text à partir d'un autre thread. Mais dans thread2, l'action dans SetText2 est exécutée dans le thread dans lequel la zone de texte a été créée
la source
la source
En termes pratiques, cela signifie que le délégué est garanti d'être appelé sur le thread principal. Ceci est important car dans le cas des contrôles Windows, si vous ne mettez pas à jour leurs propriétés sur le thread principal, vous ne voyez pas la modification ou le contrôle déclenche une exception.
Le modèle est:
la source
this.Invoke(delegate)
assurez-vous que vous appelez le délégué à l'argument surthis.Invoke()
le thread principal / le thread créé.Je peux dire qu'une règle Thumb n'accède pas à vos contrôles de formulaire sauf à partir du thread principal.
Peut-être que les lignes suivantes ont du sens pour utiliser Invoke ()
Il y a des situations où vous créez un thread Threadpool (c'est-à-dire un thread de travail), il s'exécutera sur le thread principal. Il ne créera pas de nouveau thread car le thread principal est disponible pour traiter d'autres instructions. Commencez par vérifier si le thread en cours d'exécution est le thread principal en utilisant
this.InvokeRequired
if retourne true le code actuel est en cours d'exécution sur le thread de travail, alors appelez this.Invoke (d, new object [] {text});Sinon, mettez directement à jour le contrôle de l'interface utilisateur (ici, vous êtes assuré d'exécuter le code sur le thread principal.)
la source
Cela signifie que le délégué s'exécutera sur le thread d'interface utilisateur, même si vous appelez cette méthode à partir d'un worker en arrière-plan ou d'un thread de pool de threads. Les éléments de l'interface utilisateur ont une affinité de thread - ils aiment uniquement parler directement à un thread: le thread de l'interface utilisateur. Le thread d'interface utilisateur est défini comme le thread qui a créé l'instance de contrôle et est par conséquent associé au handle de fenêtre. Mais tout cela est un détail de mise en œuvre.
Le point clé est le suivant: vous appelleriez cette méthode à partir d'un thread de travail afin de pouvoir accéder à l'interface utilisateur (pour modifier la valeur d'une étiquette, etc.) - puisque vous n'êtes pas autorisé à le faire à partir d'un autre thread que le thread de l'interface utilisateur.
la source
Les délégués sont essentiellement en ligne
Action
ouFunc<T>
. Vous pouvez déclarer un délégué en dehors de la portée d'une méthode que vous exécutez ou en utilisant unelambda
expression (=>
); parce que vous exécutez le délégué dans une méthode, vous l'exécutez sur le thread qui est en cours d'exécution pour la fenêtre / application en cours qui est le bit en gras.Exemple Lambda
la source
Cela signifie que le délégué que vous passez est exécuté sur le thread qui a créé l'objet Control (qui est le thread d'interface utilisateur).
Vous devez appeler cette méthode lorsque votre application est multithread et que vous souhaitez effectuer une opération d'interface utilisateur à partir d'un thread autre que le thread d'interface utilisateur, car si vous essayez simplement d'appeler une méthode sur un contrôle à partir d'un thread différent, vous obtiendrez un System.InvalidOperationException.
la source