WinForms многопоточный сценарий привязки данных, лучшая практика?

Например, вы можете использовать свойство width - установить его в X% или Xvw. Элементы уменьшатся, а затем вы измените размер браузера.

div {
  width: 50%;
}

Codepen

10
задан Robert Harvey 28 August 2017 в 14:58
поделиться

4 ответа

Это - тяжелая проблема начиная с большей части вывода “решений” к большому количеству пользовательского кода и большому количеству вызовов к BeginInvoke() или System.ComponentModel.BackgroundWorker (который самостоятельно является просто тонкой законченной оберткой BeginInvoke).

В прошлом я также нашел, что Вы скоро хотите задержать отправку Вашего INotifyPropertyChanged события до данных стабильны. Код, который обрабатывает одно измененное на уместность событие часто, должен читать другие правила приличия. Вы также часто имеете контроль, который должен перерисовать себя каждый раз, когда состояние одного из многих изменений свойств, и Вы не делаете бледный управление для перерисовки себя слишком часто.

Во-первых, каждое пользовательское управление WinForms должно считать все данные, которые оно должно нарисовать само в PropertyChanged обработчик событий, таким образом, это не должно блокировать объекты данных, когда это был a WM_PAINT (OnPaint) сообщение. Управление не должно сразу перекрашивать себя, когда это получает новые данные; вместо этого, это должно звонить Control.Invalidate(). Windows объединится WM_PAINT сообщения в как можно меньше запросов и только отправляют их, когда поток UI не имеет ничего иного, чтобы сделать. Это минимизирует количество перерисовок и время, объекты данных заблокированы. (Стандартные средства управления главным образом делают это с привязкой данных так или иначе),

Объекты данных должны записать то, что изменилось, поскольку изменения внесены, затем после того как ряд изменений был завершен, “ударьте” поток UI в вызов SendChangeEvents метод, который затем звонит PropertyChanged обработчик событий (на потоке UI) для всех свойств, которые изменились. В то время как SendChangeEvents() метод работает, объекты данных должны быть заблокированы для остановки фонового потока (потоков) от обновления их.

Поток UI можно “ударить” с вызовом к BeginInvoke каждый раз, когда ряду обновления считали боб из базы данных. Часто лучше иметь опрос потока UI с помощью таймера, поскольку Windows только отправляет WM_TIMER обменивайтесь сообщениями, когда очередь сообщений UI будет пуста, следовательно ведя к UI, чувствуя себя более быстро реагирующей.

Также рассмотрите привязку данных не использования вообще, и наличие UI спрашивает каждый объект данных, “что изменило” каждый раз огни таймера. Привязка данных всегда выглядит хорошей, но может быстро стать частью проблемы, скорее затем часть решения.

Как блокировать/разблокировать объектов данных, боль и может не позволить обновлениям быть считанными из базы данных достаточно быстро, можно хотеть передать поток UI (виртуальная) копия объектов данных. Наличие объекта данных быть персистентным/неизменным так, чтобы любые изменения в объекте данных возвратили новый объект данных вместо того, чтобы изменить текущий объект данных, может включить это.

Постоянные объекты звучат очень медленными, но не должны быть, видеть это и это для некоторых указателей. Также посмотрите на это и это на Переполнении стека.

Также взгляните на retlang - основанный на сообщении параллелизм в.NET. Его пакетная обработка сообщения может быть полезной.

(Для WPF у меня была бы Модель Представления, которая устанавливает в потоке UI, который был затем обновлен в 'пакетах' из многопоточной модели фоновым потоком. Однако WPF намного лучше в объединении событий привязки данных затем WinForms.)

6
ответ дан 4 December 2019 в 00:27
поделиться

Существует статья MSDN, конкретная по поводу той темы. Но будьте готовы посмотреть на VB.NET.;)

Дополнительно, возможно, Вы могли использовать Систему. ComponentModel. BackgroundWorker, вместо универсального второго потока, начиная с него приятно формализуют вид взаимодействия с порожденным фоновым потоком, который Вы описываете. Пример, данный в библиотеке MSDN, довольно достоин, поэтому пойдите посмотреть на него для подсказки, как использовать его.

Править: Пожалуйста, примите во внимание: Никакой маршалинг не требуется при использовании события ProgressChanged для передачи назад с потоком UI. Фоновый поток называет ReportProgress каждый раз, когда он имеет потребность общаться с UI. Так как возможно присоединить любой объект к тому событию нет никакой причины сделать ручной маршалинг. Прогресс передается через другую асинхронную операцию - таким образом, нет никакой потребности не волноваться ни о том, как быстро UI может обработать события прогресса, ни если фоновый поток получает interruped путем ожидания события для окончания.

Если Вы доказываете, что фоновый поток генерирует измененное событие прогресса слишком быстро затем, Вы могли бы хотеть посмотреть на Получение по запросу по сравнению с Моделями передачи для обновлений UI превосходная статья Ayende.

2
ответ дан 4 December 2019 в 00:27
поделиться

Это - проблема, которую я решил в Средствах управления Обновлением. Я поднимаю это, чтобы не предложить, чтобы Вы переписали свой код, но дать Вам некоторый источник для взгляда на для идей.

Техника, которую я использовал в WPF, состояла в том, чтобы использовать Диспетчера. BeginInvoke для уведомления приоритетного потока изменения. Можно сделать то же самое в Winforms с Управлением. BeginInvoke. К сожалению, необходимо передать ссылку на Объект формы в объект данных.

После того как Вы делаете, можно передать Действие в BeginInvoke, который запускает PropertyChanged. Например:

_form.BeginInvoke(new Action(() => NotifyPropertyChanged(propertyName))) );

Необходимо будет заблокировать свойства в объекте данных сделать их ориентированными на многопотоковое исполнение.

0
ответ дан 4 December 2019 в 00:27
поделиться

Да все книжное шоу распараллелило структуры и вызывает и т.д. Который совершенно корректен и т.д., но это может быть боль для кодирования, и часто трудно организовывать так Вас может сделать достойные тесты для него

UI только должен быть обновлен так много раз секунда, таким образом, производительность никогда не является проблемой, и опрос будет хорошо работать

Мне нравится использовать граф объектов, который непрерывно обновляется пулом фоновых потоков. Они проверяют на фактические изменения в значениях данных и когда они замечают фактическое изменение, они обновляют счетчик версии на корне графа объектов (или на каждом основном объекте вообще имеет больше смысла), и обновляет значения

Затем Ваш приоритетный процесс может иметь таймер (то же как поток UI по умолчанию), чтобы стрелять однажды приблизительно секунда и проверить счетчик версии, и если он изменяет, блокирует его (для остановки частичных обновлений) и затем обновляет дисплей

Эта простая техника полностью изолирует поток UI от фоновых потоков

2
ответ дан 4 December 2019 в 00:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: