#c# #.net #wpf #multithreading
#c# #.net #wpf #многопоточность
Вопрос:
У меня проблема, связанная с вызовами перекрестных потоков в 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));
}
}
Когда я запускаю этот код, он работает корректно для первой итерации. Однако во время второй итерации строка:
r.Dispatcher.Invoke(new ThreadStart(() => status= ((StatusButtonProperties)r.Tag).StatusInformation))
Вызывает это исключение:
Cannot use a DependencyObject that belongs to a different thread than its parent Freezable.
Я перепробовал несколько решений, но не могу найти ничего работоспособного.
Любая помощь приветствуется!
Комментарии:
1. Создание SolidColorBrush red green в потоке, который не совпадает с r.Dispatcher. Вызвать …?
2. Почему вы используете новый поток для этих установщиков? Поскольку вы используете Invoke(), он блокируется до тех пор, пока этот поток не завершит свою работу, так что это, вероятно, замедляет все это.
Ответ №1:
Я бы переписал это в:
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;
}
}));
Ответ №2:
r.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
// DO YOUR If... ELSE STATEMNT HERE
}
));
Ответ №3:
Я предполагаю, что вы находитесь в другом потоке, отличном от того, который создал эти радиокнопки. В противном случае вызов не имеет смысла. Поскольку вы создаете SolidColorBrush в этом потоке, у вас уже есть потенциальный вызов с перекрестным потоком.
Было бы разумнее сделать вызовы из разных потоков более «объемными», т. Е. поместить все в цикл foreach в одном вызове 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;
}
});
}
Вы также могли бы рассмотреть возможность использования BeginInvoke
, если разные вызовы не являются взаимозависимыми.