У меня есть окно с кнопкой, которая запускает длительную обработку.Я помещаю обработку в отдельную ветку, но, к моему удивлению, она в любом случае делает GUI замороженным.Никакой элемент управления не обновляется, я даже не могу переместить окно.
Итак вопрос в том, как запустить поток, чтобы он не мешал GUI, т. Е. Чтобы GUI всегда былв актуальном состоянии (во время обработки я изменяю данные, а графический интерфейс отображает некоторые их фрагменты)?
Вот как я начинаю поток правильно:
var thread = new Thread(doLearn);
thread.IsBackground = true;
thread.Start();
Редактировать 1
Jon:
- Я вообще не использую никаких блокировок
- Нет вызовов присоединения
- Поток пользовательского интерфейса остается один - он просто сидит там
Обработка - это большой цикл с математическими операциями, даже без выделения памяти, на стороне пользовательского интерфейса у меня есть элементы управления с привязкой (WPF) к данным, например, номер текущей итерации основного цикла.Следует обновлять каждый раз, когда основной цикл "тикает".Счетчик цикла - это свойство, которое запускает OnPropertyChanged с каждым изменением (классическая привязка WPF).
Редактировать 2 - Почти там!
Хорошо, так что Джон ударил по гвоздю в голову (кого это удивляет? ;-D) - спасибо!Проблема заключается в смене счетчика.Когда я использовал вместо Counter локальный счетчик, обновился графический интерфейс - я имею в виду, что я мог перемещать окна, но ... я не мог видеть отображение счетчика.
Что у меня здесь - WPFGUI, с такой привязкой данных
<TextBlock Text="{Binding Path=Counter"/>
и у меня есть свойство Counter, которое при каждом изменении отправляет событие PropertyChanged.Один из слушателей наверняка GUI.
Итак, Jon answer является верным «ответом», но от POV хорошего дизайна не совсем, потому что если часть GUI должна получить информацию о Counter и обновить отображениекаждые (скажем) 3 секунды, зачем кому-то использовать привязку данных?Для меня такой подход лишает законной силы идею связывания данных.
Теоретически я мог бы передать в поток обработки диспетчер GUI и выполнить всю отправку в потоке GUI, и это могло бы работать (я не пробовал)но это означало бы тесную связь не-GUI-части и GUI-части.
Пока что я не знаю, как сделать это «правильным» способом.На данный момент лучше всего создать TimerDispatcher, но не на стороне графического интерфейса, а внутри библиотеки обработки, и немедленно обновить значение счетчика, но время от времени выполнять всю отправку (хотя я еще не пробовал).
Небольшое замечание: у меня на самом деле больше свойств, связанных, например, IsRunning, который изменяется в начале и в конце обработки.И эти изменения действительно влияют на дисплей правильно, но изменение счетчика вызывает около 3000 уведомлений в течение 3-4 секунд.Так что похоже на проблему глушения.Я сделал еще один тест - я частично убил привязку данных, поэтому уведомления отправлялись, но GUI их не «получал», а слушал их.В этом случае графический интерфейс пользователя также был заморожен.
Итак, я все еще слушаю все советы - спасибо заранее за обмен.
Редактировать 3
сага продолжается здесь:
Как выполнить обработку и обновлять графический интерфейс с помощью привязки данных?