Invoke(Délégué)
Quelqu'un peut-il expliquer cette déclaration écrite sur ce lien
Invoke(Delegate):
Exécute le spécifiée délégué sur le thread qui possède la de contrôle sous-jacents de la poignée de la fenêtre.
Quelqu'un peut-il expliquer ce que cela signifie (en particulier le hardi) je ne suis pas capable de le faire clairement
- La réponse à cette question est liée à la commande.InvokeRequired bien - voir les msdn.microsoft.com/en-us/library/...
Vous devez vous connecter pour publier un commentaire.
La réponse à cette question réside dans la façon dont C# Commandes de
De De contrôle.InvokeRequired
Efficacement, ce qui Invoque n'est de s'assurer que le code que vous appelez se produit sur le thread qui a le contrôle "vit" une prévention efficace de la croix filetée exceptions.
À partir d'un point de vue historique, dans .Net 1.1, en fait, c'était autorisé. Ce que cela signifie est que vous pouvez essayer et d'exécuter du code sur le "GUI" thread partir de n'importe quel thread d'arrière-plan et ce serait surtout de travail. Parfois il suffit de cause votre application pour quitter parce que vous avez été effectivement interupting le thread GUI alors qu'il était en train de faire quelque chose d'autre. C'est le Croix Filetée Exception - imaginez que vous essayez de mettre à jour une zone de texte, tandis que le GUI est de la peinture quelque chose d'autre.
Effectivement, vous êtes interupting une file d'attente, qui peut avoir beaucoup de conséquences imprévues. Invoke est effectivement la "polis" façon d'obtenir ce que vous voulez faire dans la file d'attente, et cette règle a été appliquée à partir de .Net 2.0 partir via une levée InvalidOperationException.
De comprendre ce qui se passe réellement dans les coulisses, et ce que l'on entend par "Thread GUI", il est utile de comprendre ce qu'est un Message de la Pompe ou de la Boucle de Message est.
C'est en fait déjà répondu à la question:"Qu'est ce qu'une Pompe de Message", et il est recommandé de lecture pour comprendre le mécanisme réel qui vous sont liées en lors de l'interaction avec les contrôles de.
Autre lecture que vous pouvez trouver utile comprend:
Qu'est-ce qu'Commencer à Invoquer
et, pour un code plus lourd présentation auprès d'un échantillon représentatif:
Non valide Cross-thread Opérations
Une fois que vous avez une appréciation pour InvokeRequired, vous souhaitez peut-être envisager d'utiliser une méthode d'extension pour l'emballage de ces appels en place. C'est bien couverte dans le Débordement de la Pile question Nettoyage du Code Jonché d'Invoquer Nécessaire.
Il existe également une autre écrire de ce qui s'est passé historiquement qui peuvent être d'intérêt.
Un champ ou d'une fenêtre de l'objet dans les Windows Forms est juste un wrapper autour d'une fenêtre Win32 identifié par un poignée (parfois appelé HWND). La plupart des choses que vous faites avec le contrôle entraînera un appel Win32 API qui utilise cette poignée. La poignée est détenue par le thread qui l'a créé (généralement le thread principal), et ne devrait pas être manipulé par un autre thread. Si pour quelque raison vous avez besoin de faire quelque chose avec le contrôle à partir d'un autre thread, vous pouvez utiliser
Invoke
de demander le thread principal pour 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:
this.Invoke(() => this.Enabled = true);
Quelle que soitthis
se réfère est sûrement dans le thread courant, non?Si vous souhaitez modifier une commande, il doit être fait dans le thread dans lequel le contrôle a été créé. Cette
Invoke
méthode permet d'exécuter les méthodes de la discussion (thread qui possède le contrôle sous-jacents de la poignée de la fenêtre).En dessous de l'échantillon thread1 déclenche une exception parce que SetText1 est en train de la modifier textBox1.Du texte à 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éé
En termes concrets, cela signifie que le délégué est garanti d'être appelée par le thread principal. C'est important car dans le cas de commandes de windows si vous n'avez pas de mise à jour de leurs propriétés sur le thread principal ensuite, soit vous ne voyez pas le changement, ou le contrôle génère une exception.
Le motif est:
this.Invoke(delegate)
assurez-vous que vous appelez le délégué à l'argument dethis.Invoke()
sur le thread principal/thread créé.Je peux dire un Pouce règle de ne pas accéder à votre formulaire de contrôles à l'exception de thread principal.
Peut-être les lignes suivantes font sens pour l'aide Invoke()
Il y a des situations si vous créez un pool de threads thread(j'.e thread de travail), il sera exécuté sur le thread principal. Il ne va pas créer un nouveau fil de discussion coz thread principal est disponible pour le traitement des instructions supplémentaires. Donc d'Abord de déterminer si le thread en cours d'exécution est thread principal à l'aide de
this.InvokeRequired
retourne true si le code actuel est en cours d'exécution sur le thread de travail afin d'appelsc'.Invoke(d, new object[] { texte });
le reste directement de mise à jour de l'INTERFACE utilisateur de contrôle(Ici vous avez la garantie que vous exécutez le code sur le thread principal.)
Cela signifie que le délégué s'exécuter sur le thread de l'INTERFACE utilisateur, même si vous appelez la méthode à partir d'un fond de travailleur ou d'un thread du pool de thread. Éléments de l'INTERFACE utilisateur ont fil affinité - ils seulement envie de parler directement à un fil: 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 donc associé à la poignée de la fenêtre. Mais tout cela est un détail d'implémentation.
Le point clé est: vous appelez cette méthode à partir d'un thread de travail de sorte que vous pouvez accéder à l'INTERFACE utilisateur (pour modifier la valeur dans un label, etc) - depuis que vous êtes pas permis de le faire à partir de n'importe quel autre thread que le thread d'INTERFACE utilisateur.
Délégué sont essentiellement inline
Action
's ouFunc<T>
. Vous pouvez déclarer un délégué à l'extérieur de la portée d'une méthode qui vous êtes en cours d'exécution ou à l'aide d'unlambda
expression(=>
); parce que vous exécutez le délégué à l'intérieur d'une méthode, vous l'exécutez sur le fil qui est en cours d'exécution pour la fenêtre en cours/de l'application qui est le bit en gras.Lambda exemple
Cela signifie que le délégué vous passer est exécutée dans le thread qui a créé le Contrôle d'objet (qui est le thread d'INTERFACE utilisateur).
Vous devez appeler cette méthode lorsque votre application est multi-thread et vous souhaitez le faire d'une INTERFACE utilisateur opération à partir d'un thread autre que le thread de l'INTERFACE utilisateur, parce que si vous essayez d'appeler une méthode sur un Contrôle à partir d'un thread différent, vous aurez un Système.InvalidOperationException.