Переходя с WinForms на WPF сталкнулся с проблемой, что привычный способ доступа к визуальным компонентам из потока отличного от их создавшего немного отличается. Это выразилось в первую очерь в том, что у WPF формы нет свойства InvokeRequired.
Поэтому давайте посмотрим простой пример выполнения длительной операции в отдельном потоке.
В качестве длительной операции возьмем вот такой метод:
А в качестве тестовой формы, вот такую:

Обработчик кнопки:
Итак, реализация метода SetProgressBarValue «в лоб»:
Что логично приводит к ошибке InvalidOperationException.
Как было уже сказано, InvokeRequired отсутствует :(
Но не все так плохо как могло бы быть, в WPF для решения этой проблемы используется замечательный класс Dispatcher. Который позволяет не только получить ссылку на поток создававший визуальную часть приложения, но и запустить в этом потоке заданный метод. Таким образом метод SetProgressBarValue может быть переписан следующим образом:
Вуаля :) Все заработало
Полезные ссылки:
Для работы приложения необходим Microsoft .NET Framework 3.5 Service Pack 1
В проекте использовалась тема с codeplex
Исходники расмотренного примера можно скачать от сюда
Поэтому давайте посмотрим простой пример выполнения длительной операции в отдельном потоке.
В качестве длительной операции возьмем вот такой метод:
private int LongOperation()
{
for (int i = 0; i < 100; i++)
{
// Имитация полезной работы
Thread.Sleep(100);
// Сообщаем в визуальную часть, что часть работы выполнена
SetProgressBarValue(i + 1);
}
return 0;
}
А в качестве тестовой формы, вот такую:

Обработчик кнопки:
private void startButton_Click(object sender, RoutedEventArgs e)
{
Func<int> operation = LongOperation;
operation.BeginInvoke(null, null);
}
Итак, реализация метода SetProgressBarValue «в лоб»:
private void SetProgressBarValue(int newValue)
{
workProgress.Value = newValue;
}
Что логично приводит к ошибке InvalidOperationException.
Как было уже сказано, InvokeRequired отсутствует :(
Но не все так плохо как могло бы быть, в WPF для решения этой проблемы используется замечательный класс Dispatcher. Который позволяет не только получить ссылку на поток создававший визуальную часть приложения, но и запустить в этом потоке заданный метод. Таким образом метод SetProgressBarValue может быть переписан следующим образом:
// Делегат для перевызова метода SetProgressBarValue через диспетчер
private delegate void SetProgressBarValueHandler(int newValue);
private void SetProgressBarValue(int newValue)
{
// Проверяем совпадает ли поток диспетчера с потоком вызвавшим метод
if (Dispatcher.Thread == Thread.CurrentThread)
{
// Все замечательно :) меняем значение прогресбара
workProgress.Value = newValue;
}
else
{
// Нет :( все плохо :( перезапускаем методв в потоке диспетчера
Dispatcher.Invoke(new SetProgressBarValueHandler(SetProgressBarValue), new object[] { newValue });
}
}
Вуаля :) Все заработало
Полезные ссылки:
Для работы приложения необходим Microsoft .NET Framework 3.5 Service Pack 1
В проекте использовалась тема с codeplex
Исходники расмотренного примера можно скачать от сюда