442 votes

Quelle est la différence entre Invoke() et BeginInvoke() ?

Je me demande juste quelle est la différence entre BeginInvoke() y Invoke() sont ?

Principalement, à quoi servirait chacune d'elles.

EDIT : Quelle est la différence entre créer un objet threading et appeler invoke sur celui-ci et appeler simplement BeginInvoke() sur un délégué ? ou est-ce la même chose ?

0 votes

La déclaration devrait être : - Note : Les deux ref y out traité de la même manière au moment de la compilation, mais différent au moment de l'exécution.

627voto

Jon Skeet Points 692016

Voulez-vous dire Delegate.Invoke / BeginInvoke o 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 fil.
  • Control.Invoke : S'exécute sur le thread de l'interface utilisateur, mais le thread appelant attend l'achèvement avant de continuer.
  • Control.BeginInvoke : S'exécute sur le thread de l'interface utilisateur, et le thread appelant n'attend pas l'achèvement.

La réponse de Tim mentionne les cas où vous pourriez vouloir utiliser BeginInvoke - même s'il était surtout destiné à Delegate.BeginInvoke Je le soupçonne.

Pour les applications Windows Forms, je suggérerais que vous devriez généralement utilice BeginInvoke . De cette façon, vous n'avez pas à vous soucier des blocages, par exemple - mais vous devez comprendre que l'interface utilisateur peut ne pas avoir été mise à jour au moment où vous la regarderez la prochaine fois ! En particulier, vous ne devez pas modifier les données que le thread de l'interface utilisateur pourrait être sur le point d'utiliser pour l'affichage. Par exemple, si vous avez un Person con FirstName y LastName propriétés, et vous l'avez fait :

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

Dans ce cas, l'interface utilisateur pourrait bien finir par afficher "Keyser Spacey" (il y a une petite chance qu'elle puisse afficher "Kevin Soze", mais seulement à cause de la bizarrerie du modèle de mémoire).

A moins que vous n'ayez ce genre de problème, cependant, Control.BeginInvoke est plus facile à mettre en œuvre, et évitera à votre thread d'arrière-plan de devoir attendre sans raison valable. Notez que l'équipe de Windows Forms a garanti que vous pouvez utiliser la fonction Control.BeginInvoke d'une manière "feu et oublie" - c'est-à-dire sans jamais appeler EndInvoke . Ce n'est pas vrai pour les appels asynchrones en général : normalement, chaque BeginXXX doit avoir un appel EndXXX correspondant, généralement dans le callback.

0 votes

Je suis confus par "Control.Invoke : S'exécute sur le thread de l'interface utilisateur, mais le thread appelant attend la fin de l'exécution avant de continuer. Control.BeginInvoke : Exécute sur le thread de l'interface utilisateur, et le thread appelant n'attend pas la fin de l'opération" Je ne pense pas que Control.Invoke/BeginInvoke s'exécute sur le thread de l'interface utilisateur, ils devraient s'exécuter sur le thread qui possède le handle du contrôle (qui n'est pas toujours le thread de l'interface utilisateur). Voir MSDN

4 votes

Alors pourquoi les gens utilisent-ils Invoke plutôt que BeingInvoke ? Ne devrait-il pas y avoir quelques avantages à utiliser Invoke. Les deux exécutent des processus en arrière-plan, mais l'un est sur le même thread, l'autre sur un thread différent ?

2 votes

@Jon : Alors que j'utilise Dispatcher.BeginInvoke mon code fonctionne bien et dans Dispatcher.Invoke mon application me fait attendre quelques secondes puis elle initialise tous les contrôles puis se lance, Pouvez-vous s'il vous plaît m'aider à trouver exactement dans quel endroit je suis coincé ?

55voto

Tim Stewart Points 2500

Dans le prolongement de la réponse de Jon Skeet, il arrive que l'on veuille invoquer un délégué et attendre que son exécution soit terminée avant que le thread actuel ne continue. Dans ces cas, l'appel Invoke est ce que vous voulez.

Dans les applications multithreading, il se peut que vous ne souhaitiez pas qu'un thread attende la fin de l'exécution d'un délégué, en particulier si ce délégué effectue des E/S (ce qui pourrait bloquer le délégué et votre thread).

Dans ces cas, le BeginInvoke serait utile. En l'appelant, vous dites au délégué de commencer mais ensuite 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 arrive que l'amélioration des performances en vaille la peine.

32voto

Sujit Points 809

La différence entre Control.Invoke() y Control.BeginInvoke() est,

  • BeginInvoke() planifiera l'action asynchrone sur le thread de l'interface graphique. Lorsque l'action asynchrone est planifiée, votre code continue. Un peu plus tard (vous ne savez pas exactement quand), votre action asynchrone sera exécutée.
  • Invoke() exécutera votre action asynchrone (sur le thread de l'interface graphique) et attendra que votre action soit terminée.

Une conclusion logique est qu'un délégué que vous passez à Invoke() peut avoir des paramètres de sortie ou une valeur de retour, alors qu'un délégué que vous passez à BeginInvoke() ne le peut pas (vous devez utiliser EndInvoke pour récupérer les résultats).

26voto

KMC Points 4477

Voici un petit exemple concret pour illustrer leur différence.

new Thread(foo).Start();

private void foo()
{
  this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (ThreadStart)delegate()
    {
        myTextBox.Text = "bing";
        Thread.Sleep(TimeSpan.FromSeconds(3));
    });
  MessageBox.Show("done");
}

Si vous utilisez BeginInvoke La boîte à messages s'ouvre en même temps que la mise à jour du texte. Si vous utilisez Appeler La boîte de message apparaît après les 3 secondes de sommeil. Ainsi, en montrant l'effet d'une exécution asynchrone ( BeginInvoke ) et un synchrone ( Appeler ) appeler.

10voto

Aaron Palmer Points 4256

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 de MSDN

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