Voulez-vous dire Delegate.Invoke
/ BeginInvoke
ou Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
: S'exécute de manière synchrone, sur le même thread.
Delegate.BeginInvoke
: S'exécute de manière asynchrone, sur un threadpool
thread.
Control.Invoke
: S'exécute sur le thread d'interface utilisateur, mais le thread appelant attend la fin avant de continuer.
Control.BeginInvoke
: S'exécute sur le thread d'interface utilisateur et le thread appelant n'attend pas la fin.
La réponse de Tim mentionne quand vous voudrez peut-être l'utiliser BeginInvoke
- même si elle était principalement destinée à Delegate.BeginInvoke
, je suppose.
Pour les applications Windows Forms, je suggère que vous devriez généralement utiliser BeginInvoke
. De cette façon, vous n'avez pas à vous soucier des blocages, par exemple - mais vous devez comprendre que l'interface utilisateur n'a peut-être pas été mise à jour la prochaine fois que vous l'examinerez! En particulier, vous ne devez pas modifier les données que le thread d'interface utilisateur pourrait être sur le point d'utiliser à des fins d'affichage. Par exemple, si vous avez un Person
avec FirstName
et des LastName
propriétés, et que vous avez:
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
L'interface utilisateur pourrait bien finir par afficher "Keyser Spacey". (Il y a une chance extérieure qu'il puisse afficher "Kevin Soze" mais uniquement à travers l'étrangeté du modèle de mémoire.)
À moins que vous n'ayez ce genre de problème, cependant, il Control.BeginInvoke
est plus facile de résoudre le problème et évitera à votre thread d'arrière-plan d'attendre sans raison valable. Notez que l'équipe Windows Forms a garanti que vous pouvez utiliser Control.BeginInvoke
d'une manière "tirer et oublier" - c'est-à-dire sans jamais appeler EndInvoke
. Ce n'est pas le cas des appels asynchrones en général: normalement, chaque BeginXXX doit avoir un appel EndXXX correspondant, généralement dans le rappel.
En s'appuyant sur la réponse de Jon Skeet, il y a des moments où vous souhaitez invoquer un délégué et attendre que son exécution se termine avant que le thread actuel ne continue. Dans ces cas, l'appel Invoke est ce que vous voulez.
Dans les applications multithread, il se peut que vous ne souhaitiez pas qu'un thread attende un délégué pour terminer l'exécution, en particulier si ce délégué effectue des E / S (ce qui pourrait rendre le délégué et votre bloc de threads).
Dans ces cas, BeginInvoke serait utile. En l'appelant, vous dites au délégué de démarrer, mais votre thread est libre de faire d'autres choses en parallèle avec le délégué.
L'utilisation de BeginInvoke augmente la complexité de votre code mais il y a des moments où l'amélioration des performances vaut la complexité.
la source
La différence entre
Control.Invoke()
etControl.BeginInvoke()
est,BeginInvoke()
planifiera l'action asynchrone sur le thread GUI. Lorsque l'action asynchrone est planifiée, votre code continue. Quelque temps plus tard (vous ne savez pas exactement quand) votre action asynchrone sera exécutéeInvoke()
exécutera votre action asynchrone (sur le thread GUI) et attendra que votre action soit terminée.Une conclusion logique est qu'un délégué auquel vous passez
Invoke()
peut avoir des paramètres de sortie ou une valeur de retour, tandis qu'un déléguéBeginInvoke()
auquel vous passez ne peut pas (vous devez utiliser EndInvoke pour récupérer les résultats).la source
Juste pour donner un court exemple pratique pour voir un effet de leur différence
Si vous utilisez BeginInvoke , MessageBox apparaît simultanément à la mise à jour du texte. Si vous utilisez Invoke , MessageBox apparaît après les 3 secondes de sommeil. Par conséquent, montrant l'effet d'un appel asynchrone ( BeginInvoke ) et synchrone ( Invoke ).
la source
Delegate.BeginInvoke () met en file d'attente de manière asynchrone l'appel d'un délégué et renvoie immédiatement le contrôle. Lorsque vous utilisez Delegate.BeginInvoke (), vous devez appeler Delegate.EndInvoke () dans la méthode de rappel pour obtenir les résultats.
Delegate.Invoke () appelle de manière synchrone le délégué dans le même thread.
Article MSDN
la source
Il suffit d'ajouter pourquoi et quand utiliser Invoke ().
Invoke () et BeginInvoke () rassemblent le code que vous spécifiez sur le thread du répartiteur.
Mais contrairement à BeginInvoke (), Invoke () bloque votre thread jusqu'à ce que le répartiteur exécute votre code. Vous souhaiterez peut-être utiliser Invoke () si vous devez suspendre une opération asynchrone jusqu'à ce que l'utilisateur ait fourni une sorte de rétroaction.
Par exemple, vous pouvez appeler Invoke () pour exécuter un extrait de code qui affiche une boîte de dialogue OK / Annuler. Une fois que l'utilisateur a cliqué sur un bouton et que votre code marshalé est terminé, la méthode invoke () revient et vous pouvez réagir à la réponse de l'utilisateur.
Voir Pro WPF dans C # chapitre 31
la source