I have an issue regarding cross thread calls in 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));
}
}
When I run this code, it works correctly for the first iteration. However during the second iteration the line:
r.Dispatcher.Invoke(new ThreadStart(() => status= ((StatusButtonProperties)r.Tag).StatusInformation))
Causes this exception:
Cannot use a DependencyObject that belongs to a different thread than its parent Freezable.
I've tried a few solutions but I can't fin开发者_如何转开发d anything workable.
Any help appreciated!
I'd rewrite this to:
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
}
));
I am assuming that you are in a different thread than the one which created those RadioButtons. Otherwise the invoking makes no sense. Since you are creating the SolidColorBrush in that thread, you already have a potential cross-thread call there.
It would make more sense to make the cross-thread calls more "chunky", i.e. put everything in the foreach loop in a single Invoke call.
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;
}
});
}
You could also consider using BeginInvoke
if the different calls are not interdependant.
精彩评论