#c# #wpf #multithreading #simulation
#c# #wpf #Многопоточность #Симуляция
Вопрос:
У меня есть процесс моделирования, который состоит из итераций, в которых симулятор вычисляет некоторые данные и таким образом, с каждой итерацией перемещается через дискретное время. Помимо этого симулятор должен через некоторые периодические интервалы обновлять параметры компонентов новыми данными. Компоненты симулятора используются при расчете итераций.
Моя текущая модель основана на таймере с интервалом в 20 секунд. Для каждого такта таймера симулятор сначала вычисляет 20 итераций как можно быстрее, а в остальное время (20 секунд — время для имитации 20 итераций) обновляет параметры компонентов новыми данными, если новые данные доступны. Это работает очень хорошо, но…
… я реализовал визуализатор в WPF с использованием шаблона MVVM, и я хочу, чтобы этот визуализатор, один раз при запуске моделирования, показывал состояние каждой итерации через правильный интервал времени. Итак, если каждая итерация представляет собой временной интервал в 1 секунду, я хочу, чтобы визуализатор каждую секунду менял состояние визуализации. Я сделал это, используя таймер в визуализаторе и буфер для состояний в симуляторе. По сути, симулятор помещает вычисленные состояния в очереди, а визуализатор выводит состояния из очереди для каждого такта таймера. Это хорошо работает, за некоторыми исключениями.
- Сложно обеспечить постоянный интервал тика (это зависит от процесса, приоритета потока и т.д.), Поэтому очередь увеличивается до бесконечности, если таймер визуализатора работает медленнее, чем таймер симулятора, или наоборот, когда визуализатор работает быстрее.
- Использование очередей и кода реализации для всех данных, которые я хочу визуализировать, представляется мне как затраты времени на реализацию и памяти.
Итак, я думал об альтернативном решении. У меня есть один таймер в визуализаторе, и для каждого тика таймера в фоновом потоке вызывается асинхронный метод для вычисления новой итерации в симуляторе. При асинхронном обратном вызове в визуализаторе визуализатор обновляет визуализацию на основе нового вычисленного состояния в симуляторе. При таком подходе у меня возникает проблема с обновлением компонентов симулятора, потому что им требуется больше времени для обновления, чем длительность одного интервала таймера. Возможно, я мог бы поместить обновление компонентов в новый фоновый поток, и как только обновление будет выполнено, просто вызовите метод в компонентах, который скопирует новое значение в значение параметров компонентов.
Кроме того, симулятор работает в режиме реального времени, поэтому он должен идти в ногу с реальным временем.
Было бы полезно, если бы вы могли сказать мне, какой подход лучше и как я могу улучшить подходы, но также, если у кого-то есть лучший подход, я был бы рад прочитать его и использовать 🙂
Спасибо.
Ответ №1:
поскольку вы используете WPF, если вы используете привязку данных, ваш пользовательский интерфейс будет автоматически обновляться при обновлении данных — за некоторыми исключениями, в основном элементами в ObservableCollections. Если вы используете ObservableCollections, вам пришлось бы привязываться к каждому отдельному элементу в коллекции. вы могли бы сделать это вручную или написать класс, производный от OC, который выполняет это при добавлении элемента и отсоединяется при удалении элемента (это важно, чтобы избежать утечек памяти)
Комментарии:
1. Я сказал, что использую шаблон MVVM, но у меня есть одно исключение, в моей модели «inotify свойство изменено» не реализовано обычным способом. У меня есть таймер в визуализаторе, который вызывает метод обновления моделей представления, который затем считывает состояние симулятора, а затем при изменении свойства viewmodel повышается значение inotifypropertychanged.
2. вы пробовали автоматическое («обычным» способом) обновление вместо ручного?
3. Я этого не сделал, потому что не хочу, чтобы модель знала о view model, потому что модель может использоваться в консольном приложении, а не только в приложении на основе WPF. Но я рассматривал, что модель вызывает изменение inotifyproperty. Также я полагаю, что это учитывало бы секундный подход.
4. вы могли бы сделать это INotifyPropertyChange … консоль не будет заботиться об этом… вы могли бы даже добавить некоторый тип логического значения, чтобы он «знал» его в консольном режиме и, таким образом, не вызывал события изменения
Ответ №2:
вместо использования таймера для обновления вы также можете использовать привязку данных в wpf, когда вы использовали архитектуру mvvm, и было бы неплохо включить **
inotifypropertychanged
** создайте класс в вашей модели представления и привяжите элементы непосредственно к компонентам, чтобы ваша проблема была решена