Одной из проблем при работе в WPF с визуальными компонентами заключается в том, что доступ к ним из любого потока отличного от их породившего приводит к исключению.
Для примера возьмем простое приложение, со следующим интерфейсом:
При нажатии на кнопку "Старт" запускается длительная операция выводящая состояние процесса в ProgressBar.
Код метода длительной операции для простоты возьмем вот такой:
private int LongOperation()
{
for (int i = 0; i < 100; i++)
{
// Имитация полезной работы
Thread.Sleep(100);
// Сообщаем в визуальную часть, что часть работы выполнена
SetProgressBarValue(i + 1);
}
return 0;
}
* This source code was highlighted with Source Code Highlighter.
Обработчик клика на кнопке:
private void startButton_Click(object sender, RoutedEventArgs e)
{
Func<int> operation = LongOperation;
operation.BeginInvoke(null, null);
}
* This source code was highlighted with Source Code Highlighter.
При попытке реализовать метод SetProgressBarValue в лоб:
private void SetProgressBarValue(int newValue)
{
workProgress.Value++;
}
* This source code was highlighted with Source Code Highlighter.
мы получим InvalidOperationException
Для решения этой проблемы необходимо воспользоваться замечательным классом Dispatcher, переписав с его помощью код, мы получим:
// Делегат для перевызова метода 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 });
}
}
* This source code was highlighted with Source Code Highlighter.
Вуаля, все заработало :)
Проект можно скачать здесь: MultithreadingWPF.rar
Этот комментарий был удален автором.
ОтветитьУдалитьВ .net есть стандартный класс BackgroundWorker, который позволяет выполнить длительную операцию в отдельном, потоке. Он собственно и предназначен для решения подобных задач. И какой смысл изобретать велосипед?
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалить