2011-06-13 6 views
6

L'appel d'un thread d'interface utilisateur à partir d'un thread de travail est discuté plusieurs fois et nous savons pourquoi utiliser BeginInvoke() au lieu de Invoke(). J'ai récemment posté this question et après avoir fait quelques recherches, j'ai découvert qu'il y a au moins trois façons différentes (en interne, elles peuvent être identiques) d'invoquer (de manière asynchrone) quelque chose sur le thread de l'interface utilisateur.control.BeginInvoke() Vs Dispatcher Vs SynchronizationContext Vs. .. - FIABILITÉ

  1. Control.BeginInvoke()
  2. L'utilisation SynchronizatoinContext classe
  3. En utilisant Dispatcher.BeginInvoke(priority..)

Quelqu'un peut-il me dire ce qui est un moyen fiable d'appeler de manière asynchrone une méthode à exécuter sur thread d'interface utilisateur. Une expérience? Je vois Dispatcher.BeginInvoke a le composant prioritaire, le rend-il plus fiable?

Contexte:
nous utilisons someControl.BeginInvoke() mais on a remarqué que, parfois, (malheureusement seulement dans l'environnement de production d'utilisateur final) le délégué passé à BeginInvoke is jamais exécuté ce qui me fait croire que le message de message qu'il crée se perd. Nous voulons un moyen fiable de communiquer avec le thread de l'interface utilisateur. control.Invoke() parfois suspendre l'interface utilisateur, donc nous ne voulons pas y aller non plus.

+0

Ne confondez pas WinForms avec WPF. – SLaks

+0

J'ai un problème similaire ... avez-vous réussi à résoudre le problème? –

+0

même ici, n'importe quelle mise à jour? – Pedro77

Répondre

0

Ils fonctionnent tous comme ils le devraient, si vous appelez BeginInvoke et parfois rien ne se passe, il y a un problème dans l'environnement ou le code d'appel, probablement - ce n'est pas que BeginInvoke n'est pas fiable. Bien - il pourrait y avoir un bug, mais c'est beaucoup moins probable.

Peut-être que vous pourriez donner plus de contexte et nous pouvons vous aider à diagnostiquer.

+0

Merci pour la réponse. J'ai un scénario similaire dans notre code. http://stackoverflow.com/questions/6270514/control-begininvoke-fails-to-call-the-delegate – karephul

+0

Salut karephul, c'est intéressant mais ça n'aide pas beaucoup dans ce cas puisqu'ils n'ont pas non plus trouvé de réponse . Quelle est votre configuration de base en termes de threads, processus, verrous, etc? –

+0

Oh ... c'est le même problème? Juste reposted ici? –

0

SynchronizationContext est plus abstrait et adaptable dans plus de cas. C'est un emballage de mise en œuvre spécifique. MSDN indique "Les fournisseurs de modèles de synchronisation peuvent étendre cette classe et fournir leurs propres implémentations pour ces méthodes".

+0

SynchronizationContext est présenté ici: http://social.msdn.microsoft.com/Forums/en-US/async/thread/1218c86e-fa9b-45a6-93b0-5e27616a6c21 – Steel

0

Vous devez être prudent avec les fonctions lambda et BeginInvoke. J'avais un code comme celui-ci qui entraînait toutes sortes de comportements bizarres.

MyThing thing; 
while(GetThing(ref thing)) { 
    control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
} 

Le problème est que thing n'est pas évaluée lors de la création de la fonction lambda. Il est évalué lorsque la fonction lamdba est exécutée. Mais il est lié à une variable qui change en même temps dans le thread producteur.

Vous pouvez résoudre ce problème en déclarant une copie variable locale de thing

MyThing thing; 
while(GetThing(ref thing)) { 
    MyThing thing_x = thing; 
    control.BeginInvoke((Action)(() => control.Text = thing_x.ToString())); 
} 

Ou vous pouvez mettre la laideur BeginInvoke dans un emballage

MyThing thing; 
while(GetThing(ref thing)) { 
    SetText(thing); 
} 

void SetText(MyThing thing) 
    control.BeginInvoke((Action)(() => control.Text = thing.ToString())); 
}