Accès aux objects croisés WPF

J’ai un problème concernant les appels croisés dans WPF.

foreach (RadioButton r in StatusButtonList) { StatusType status = null; r.Dispatcher.Invoke(new ThreadStart(() => status= ((StatusButtonProperties)r.Tag).StatusInformation)); if (AppLogic.CurrentStatus == null || AppLogic.CurrentStatus.IsStatusNextLogical(status.Code)) { SolidColorBrush green = new SolidColorBrush(Color.FromRgb(102, 255, 102)); r.Dispatcher.Invoke(new ThreadStart(() => r.Background = green)); } else { SolidColorBrush red = new SolidColorBrush(Color.FromRgb(255, 0, 0)); r.Dispatcher.Invoke(new ThreadStart(() => r.Background = red)); } } 

Lorsque je lance ce code, il fonctionne correctement pour la première itération. Cependant, lors de la deuxième itération, la ligne:

  r.Dispatcher.Invoke(new ThreadStart(() => status= ((StatusButtonProperties)r.Tag).StatusInformation)) 

Provoque cette exception:

 Cannot use a DependencyObject that belongs to a different thread than its parent Freezable. 

J’ai essayé quelques solutions mais je ne trouve rien qui puisse fonctionner.

Toute aide appréciée!

Je réécrirais ceci pour:

 r.Dispatcher.Invoke(new Action(delegate() { status = ((StatusButtonProperties)r.Tag).StatusInformation; if (AppLogic.CurrentStatus == null || AppLogic.CurrentStatus.IsStatusNextLogical(status.Code)) { r.Background = Brushes.Green; } else { r.Background = Brushes.Red; } })); 
  r.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Normal, new Action( delegate() { // DO YOUR If... ELSE STATEMNT HERE } )); 

Je suppose que vous êtes dans un fil différent de celui qui a créé ces RadioButtons. Sinon, l’invocation n’a aucun sens. Étant donné que vous créez SolidColorBrush dans ce fil, vous avez déjà un appel cross-thread potentiel.

Il serait plus logique de rendre les appels inter-thread plus “en gros morceaux”, c’est-à-dire de tout mettre dans la boucle foreach dans un seul appel Invoke.

 foreach (RadioButton r in StatusButtonList) { r.Dispatcher.Invoke(new ThreadStart(() => { StatusType status = ((StatusButtonProperties)r.Tag).StatusInformation; if (AppLogic.CurrentStatus == null || AppLogic.CurrentStatus.IsStatusNextLogical(status.Code)) { SolidColorBrush green = new SolidColorBrush(Color.FromRgb(102, 255, 102)); r.Background = green; } else { SolidColorBrush red = new SolidColorBrush(Color.FromRgb(255, 0, 0)); r.Background = red; } }); } 

Vous pouvez également envisager d’utiliser BeginInvoke si les différents appels ne sont pas interdépendants.