вторник, 11 августа 2015 г.
Показ окна в отдельном потоке
понедельник, 23 ноября 2009 г.
Создание окна из потока отличного от потока диспетчера приложения
public void StartReadFromScala(Guid idWorkflow)
{
WndReadFromScala form = new WndReadFromScala();
form.Show();
}
* This source code was highlighted with Source Code Highlighter.
Выполнялось, но форма не появлялась :(
Пришлось пойти на следующее ухищрение:
public void StartReadFromScala(Guid idWorkflow)
{
// Создаем форму для ввода данных, но создаем ее в главном потоке
Application.Current.Dispatcher.Invoke(new NoParamHandler(CreateWndReadFromScala), new object[] { });
}
private void CreateWndReadFromScala()
{
WndReadFromScala form = new WndReadFromScala();
form.Show();
}
* This source code was highlighted with Source Code Highlighter.
А вот теперь все работает ;)
среда, 12 августа 2009 г.
Выполнение кода после изменения текста в ComboBox
В XAML все просто:
<ComboBox SelectionChanged="ComboBox_SelectionChanged" >
<ItemsControl>1</ItemsControl>
<ItemsControl>2</ItemsControl>
<ItemsControl>3</ItemsControl>
<ItemsControl>4</ItemsControl>
</ComboBox>
* This source code was highlighted with Source Code Highlighter.
Но если в обработчике события тупо вызывать MessageBox.Show возникает проблема: пользователь уже видит MessageBox, а изменение текста еще не произошло :( Что может ввести пользователя в заблуждение.
Решить проблему можно вот таким достаточно извращенным способом:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DispatcherTimer t = null;
t = new DispatcherTimer(new TimeSpan(1), DispatcherPriority.Background, (s, e1) => { t.Stop(); MessageBox.Show("asdfvasdvc"); }, this.Dispatcher);
t.Start();
}
* This source code was highlighted with Source Code Highlighter.
Но надо будет еще подумать... что то ведь должно быть проще.
вторник, 19 мая 2009 г.
Многопоточный доступ в WPF
Одной из проблем при работе в 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