Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.89/18: Рейтинг темы: голосов - 18, средняя оценка - 4.89
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923

MVVM Утечка памяти

12.06.2022, 20:22. Показов 4573. Ответов 82
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Собственно сделал подписку: _messageService.MessagesChanged += OnMessagesChanged; в VM.
А отписывать-то как?

Сделал так:

https://github.com/LimeniyeCyb... del.cs#L82

Но даже не понимаю.что сделал. Этого будет достаточно?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.06.2022, 20:22
Ответы с готовыми решениями:

Утечка памяти с картинками
у меня есть вот такой контрол <StackPanel x:Name="StackEmoji" Grid.Row="1" Grid.Column="1" ...

Dispatch timer - Утечка памяти
Всем привет. Пишу на подобные форумы первый раз. Хотел бы попросить помочь разобраться в ситуации с "утечкой памяти". Есть...

Утечка памяти в Awesomium WebControl
Всем привет. Использую в качестве встроенного браузера Awesomium, но вот проблема, уже страниц через 20 процесс awesomium_process.exe...

82
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,761
Записей в блоге: 4
16.06.2022, 21:59
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
C#
1
BindingOperations.EnableCollectionSynchronization (ICollection.SyncRoot);
Да, читал про это, но манёк не то... Везде советуют именно модифицированную ObservableCollection... Осталось разобраться в этой куче предложений
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
16.06.2022, 22:07
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Везде советуют именно модифицированную ObservableCollection...
Обычно "модифицируют" через маршалинг всех операций в UI поток.
Это подойдёт только для редко обновляемой коллекции единичными элементами.
Для быстрых обновлений и/или пакетных обновлений нужна локировка.
2
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
16.06.2022, 22:22  [ТС]
Элд Хасп, я просто ни разу не видел синглтон VM и мне это упёрто не даёт покоя: "да как это так-то, в VM и синглтон?!".

Вроде как VM, это просто коннектор, что-то простое, без лишних сложных реализаций по типу этого же синглтона, разве нет?
Пока синглтон -- очень удобный вариант для решения проблемы с утечкой памяти, но я сомневаюсь в его надёжности. Мне кажется, что такими действиями я навязываю ему функциональность уровня модели.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
16.06.2022, 23:22
Цитата Сообщение от limeniye Посмотреть сообщение
я просто ни разу не видел синглтон VM и мне это упёрто не даёт покоя: "да как это так-то, в VM и синглтон?!".
Зависит от задачи.
Очень часто это возможно и значительно упрощает реализацию приложения.
Те же локаторы и сервисы по сути создают тот же самый синглтон, но не на уровне ViewModel, а на уровне View.

Синглтон несколько нарушает принципы ООП и Solid, так как VM не может знать сколько её экземпляров понадобятся View.
Но в реальных приложениях вам часто приходилось сталкиваться с динамическим пересозданием VM и/или создание нескольких её экземпляров?
Такое бывает нужно очень редко.

При достаточном опыте, надобность в синглтонах отпадает, так как довольно хорошо представляешь себе как всё друг с другом связанно и ошибок работы с разными экземплярами просто не допускаешь.
Поэтому на более высоком уровне (знаний), синглтоны редко используются.

Добавлено через 4 минуты
Цитата Сообщение от limeniye Посмотреть сообщение
Вроде как VM, это просто коннектор, что-то простое, без лишних сложных реализаций по типу этого же синглтона, разве нет?
В идеале VM - это прокси отражающее Модель через свои свойства.
Но если у вас одна Модель (а это 99% приложений), то можно и Модель и VM сделать синглтонами.
Что сложного вы увидели в реализации синглтона - я не понимаю.
Для этого нужно только закрыть её единственный конструктор и предоставить единственный экземпляр через статическое свойство.

Добавлено через 3 минуты
Цитата Сообщение от limeniye Посмотреть сообщение
я сомневаюсь в его надёжности
Надёжности в чём?
Как бы безопасность он несколько ухудшает, так как к статическому экземпляру есть доступ отовсюду.
Но если вы хотите строить действительно безопасное (с точки зрения хака) приложение, то Шарп в целом для этого не шибко подходит.
1
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
16.06.2022, 23:30  [ТС]
Элд Хасп, ну получается так, что я создаю Model в singlton, а потом ещё и Vm в singlton. Всё singlton'ю, а по сути синглтон вообще
Цитата Сообщение от Элд Хасп Посмотреть сообщение
несколько нарушает принципы ООП и Solid
Мне кажется singlton'a в Model достаточно, просто в VM нужно сделать отписку от события в определённый момент, например реализовав IDisponsable интерфейс, на всякий случай.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
17.06.2022, 00:03
Цитата Сообщение от limeniye Посмотреть сообщение
просто в VM нужно сделать отписку от события в определённый момент
Определённый момент - это перед тем как вы затираете последнюю ссылку на экземпляр VM.
По вашим словам такого момента в вашем приложении нет.
Если так, то значит вы где-то, сами не зная того, создаёте новые ненужные экземпляры VM.
И надо выявить где это происходит и пресечь это.

Цитата Сообщение от limeniye Посмотреть сообщение
например реализовав IDisponsable интерфейс, на всякий случай.
Вы реализовали "а кабы был!".
Он у вас ничего не делает, нигде не вызывается, и только захламляет код.
Dispose() - должен вызываться для освобождения НЕУПРАВЛЯЕМЫХ ресурсов.
И где у вас такие?

Цитата Сообщение от limeniye Посмотреть сообщение
Собственно сделал подписку: _messageService.MessagesChanged += OnMessagesChanged; в VM.
А отписывать-то как?
Если у вас экземпляр VM не должен существовать до конца сеанса приложения, то нужно:
Цитата Сообщение от Элд Хасп Посмотреть сообщение
_messageService.MessagesChanged надо сделать слабым событием, чтобы подписка на него не удерживала экземпляр
Но по вашим словам у вас экземпляр VM существует всё время сеанса, вы его никогда не уничтожаете, следовательно и сложности эти не к чему.
Надо искать где вы создаёте ненужные экземпляры VM, если дело, вообще, в этом.
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
17.06.2022, 14:41  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если так, то значит вы где-то, сами не зная того, создаёте новые ненужные экземпляры VM.
И надо выявить где это происходит и пресечь это.
Мне просто сказали: "в Вас есть утечка памяти".

По-моему это было тут
https://github.com/LimeniyeCyb... ewModel.cs

(а может и не тут, я не помню). В общем, почему утечка -- не знаю, я маслёнок в этом (

Нужно почитать и посмотреть на эту тему тем.
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,761
Записей в блоге: 4
18.06.2022, 13:09
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Самый простой способ это работа в VM с ObservableCollection через ICollection.SyncRoot.
Получается вот это работает в VM, что-то типа такого
C#
1
2
3
4
5
6
7
8
ICollection myCollection = someCollection;
lock(myCollection.SyncRoot)
{
    foreach (object item in myCollection)
    {
        // Insert your code here.
    }
}
А вот где делать вызов BindingOperations.EnableCollectionSynchronization (ICollection.SyncRoot);? Ведь эта штука из

Namespace:
System.Windows.Data
Assembly:
PresentationFramework.dll


BindingOperations.EnableCollectionSynchronization Method

Можно какой нить простой примерчик для MVVM?
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
18.06.2022, 14:13  [ТС]
Andrey-MSK, как я понял вот так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public ObservableCollection<Students> Students { get; } = new ObservableCollection<Student>();
 
public MainViewModel()
{
    BindingOperations.EnableCollectionSynchronization (((ICollection)Students).SyncRoot);
    _someModel.Added += OnStudentAdded;
}
 
private void OnStudentAdded(object sender, Student student)
{
    lock(((ICollection)Students).SyncRoot)
    {
        Students.Add(student);
    };
}
Добавлено через 2 минуты
Но если да, тогда я не понимаю зачем нужна тогда строка 5.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 14:49
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А вот где делать вызов BindingOperations.EnableCollectionSynchr onization (ICollection.SyncRoot);? Ведь эта штука из:
По простому - в конструкторе VM при условии что она создаётся в UI потоке (99.9% реальных задач).
По феншую - при создании экземпляра VM на уровне App, там же происходит и вызов этого метода или передавать в VM делегат метода вызова.

Так же надо помнить что если возможна замена коллекции или VM нужно уничтожить, то нужно отписывать привязки от коллекции (DisableCollectionSynchronization).

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Получается вот это работает в VM, что-то типа такого
В самом простом варианте да.
Для очень динамичного изменения, можно реализовать локировку только во время записи.

Добавлено через 8 минут
Цитата Сообщение от limeniye Посмотреть сообщение
как я понял вот так
Тоже верно.
Вероятность очень маленькая, то всё же есть когда по времени совпадут обновления UI и добавление единичного элемента.
Но это (как и пример от Andrey-MSK) скорее относится к потокобезопасности чем к исключениям от обновления из других потоков.
Для предотвращения исключений в представлении достаточно просто уведомить о локере и потом можно "забыть" про это.

А вот для группового обновления (AddRange) это весьма полезно, так как до завершения всех обновлений коллекции обновление её представления не будет происходить.

Цитата Сообщение от limeniye Посмотреть сообщение
Но если да, тогда я не понимаю зачем нужна тогда строка 5.
В WPF без неё, если вызвать метод OnStudentAdded не из UI потока - будет исключенее.
В UWP - не будет.
1
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
18.06.2022, 14:53  [ТС]
Элд Хасп, то есть по сути эта строка свойству SyncRoot коллекции задаёт текущий Dispatcher ?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 15:05
Цитата Сообщение от limeniye Посмотреть сообщение
то есть по сути эта строка свойству SyncRoot коллекции задаёт текущий Dispatcher ?
В какой-то мере.
Это нюансы реализации ItemsControl.
Если есть локер, то происходит маршалинг CollectionChanged в UI поток.
Если нет локера, то просто выкидывается исключение.
Сделано так из-за того, что ItemsControl не знает какой механизм потокобезопасности будет использован при работе с коллекцией.
Для более сложных способов (чем простой локер) используется перегрузка EnableCollectionSynchronization(IEnumerable, Object, CollectionSynchronizationCallback).
Поэтому в простых случаях, достаточно уведомить о локере, чтобы просто предотвратить выброс исключений.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 15:55
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Сделано так из-за того, что ItemsControl не знает какой механизм потокобезопасности будет использован при работе с коллекцией.
Не совсем верно - уточню.
ItemsControl контрол - это DependecyObject. Дефолтным для DependecyObject является обеспечение поткобезопасности через работу работу со всеми данными в одном и том же потоке связанном с Диспетчером этого DependecyObject.
Если же изменение данных происходит в других потоках, то для ItemsControl - это неизвестный механизм и происходит выкидывание исключения.

Вообще, конечно, с маршалингом событий в MS перемудрили.
В WPF PropertyChanged автоматически маршализируется в UI поток, а CollectionChanged и CanExecuteChanged - нет.
В UWP - наоборот: CollectionChanged и CanExecuteChanged - маршализируются , а PropertyChanged - нет.
Зачем эту путаницу ввели - ума не приложу.
Сделали бы для всех маршалинг или без него.
Из-за этого приходится учитывать особенности типа View на уровне VM и даже, иногда, Model.
Если бы не это, то почти всегда можно было бы реализовывать VM в Standard.
И уже потом выбирать какого типа подключать к ней View.
1
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
18.06.2022, 16:47  [ТС]
Элд Хасп, Вы постоянно говорите "маршалинг".
Но для меня это очень расплывчатая тема. Искал по этому поводу информацию: это вообще для среиализации и дессериализации данных. Есть ещё класс Marshal, как мне помнится, он вроде что-то там с неуправляемыми ресурсами делает
Что такое класс Marshal

Вообще путаюсь зачем вообще нужен "маршалинг"
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 17:05
Цитата Сообщение от limeniye Посмотреть сообщение
Вы постоянно говорите "маршалинг".
Я не знаю откуда взялся этот термин, но вот пример его использования //Cant do this from a background thread and has to marshal.
Marshal - очень многозначное слово. Возможно в программировании используется смысл "размещать".

Надо поинтересоваться о происхождении термина у тех кто более подкован в теории и основах Шарпа.
OwenGlendower и kolorotur можете что-то прояснить?

Добавлено через 3 минуты
limeniye, что интересно - Гугл переводчик не переводит его на русский смысл, а транслитерирует.
То есть по его мнению, это уже устойчивый термин и для русского программ. сленга.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 17:08
limeniye, вот и русское толкование: Маршалинг
Применение
Маршалинг применяется при передаче данных между процессами и/или потоками, например:

- при использовании различных механизмов RPC;
- при использовании P/Invoke на платформе .NET Framework (при переходе от неуправляемого типа в тип CLR);
Добавлено через 2 минуты
Маршалинг события - это получение данных из метода вызванного в одного потоке и вызов метода с этими данными в другом потоке.
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
18.06.2022, 17:30  [ТС]
Я понимаю как сереализовать .xml или .json формат в какой-то CLR тип, например.
Не знаю как это работает под капотом, но думаю это не особо важно.

Я более-менее пониманию как работает RPC сериализация: перевод в байты и десериализация байт в CLR.

А вот:
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Обычно "модифицируют" через маршалинг всех операций в UI поток.
совсем не понимаю. Для чего тут нужна эта преславуя "сериализация" (она же "маршалинг", как я понял -- это одно и то же) ?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.06.2022, 18:09
Цитата Сообщение от Элд Хасп Посмотреть сообщение
можете что-то прояснить?
Оно в шарп и другие языки из английского пришло: маршал — ответственный за движение/направление кого/чего-либо.
Работник аэродрома, машущий самолетам фонариками или принимающий/запускающий с авианосцев — маршал.
to marshal (маршаллить) — производный глагол. ЖД вагоны на сортировочной станции маршаллятся.
Не проверял, но не удивлюсь если звание Маршал в вооруженных силах оттуда же (или наоборот) — тот, кто движет войсками.

Marshal в программировании — часть системы, ответственная за направление/перевод данных из одной среды в другую: в шарпе — из неуправляемой в управляемую и наоборот.
2
18.06.2022, 18:27

Не по теме:

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
И да, в VM using System.Windows;, из-за Application.Dispatcher, нужно найти реализацию потоконезависимой ObservableCollection...
https://github.com/reactivemarbles/DynamicData

0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
18.06.2022, 19:53
Цитата Сообщение от limeniye Посмотреть сообщение
совсем не понимаю. Для чего тут нужна эта преславуя "сериализация" (она же "маршалинг", как я понял -- это одно и то же) ?
Сериализация вовсе не причём.
Относительно ObservableCollection - это перекидка события CollectionChanged (обычно метода подымающего событие) в UI поток.

Простейший пример такого "модифицированного" ObservableCollection:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public class DispatcherObservableCollection<T> : ObservableCollection<T>
    {
        private static readonly Dispatcher staticDispatcher = Application.Current.Dispatcher;
 
        public DispatcherObservableCollection()
        {
        }
 
        public DispatcherObservableCollection(IEnumerable<T> collection) : base(collection)
        {
        }
 
        public DispatcherObservableCollection(List<T> list) : base(list)
        {
        }
 
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            // Проверка потока.
            if (staticDispatcher.CheckAccess())
                base.OnCollectionChanged(e);
            else
                // Маршалинг вызова метода в поток диспетчера.
                staticDispatcher.BeginInvoke(OnCollectionChanged, e);
        }
    }
Добавлено через 10 минут
Проблема такой реализации в зависимости Dispatcher от типа View и как следствие несовместимость реализаций Framework, Core (.Net), UWP.
По идее такой класс должен писаться на Standard, а в нём нет Dispatcher.
Приходится определять контекст синхронизации потоков слушателей и маршилировать в них.
Такая реализация уже значительно сложнее.
Пример для команд: Исполнение делегатов обобщённого типа
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.06.2022, 19:53

Возможна ли утечка памяти в следующем коде
Имеем следующу последовательность высокочастотных операций, требуется оптимизация т к память съедает в течении дня до 1 Гб: ...

Утечка памяти при обновлении текста TextBlock
При каждом тике таймера обновляется текст TextBlock'a. private void Paint(object sender, EventArgs e) { ...

Утечка памяти при большом количестве сообщений
Есть окно сообщения.При новом сообщения создается новое окно(анимировано),старое закрывается(Close).В этом окне есть одно Image.Если много...

Программа не может продолжить работу, так как недостаточно памяти. Утечка в WPF?
В общем, есть у меня контрол, который наследует от Image, воспроизводит анимацию просто сменяя изображения из массива. А сменяются...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru