Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Слабые ссылки WeakReference / 6 сообщений из 6, страница 1 из 1
03.08.2014, 18:52
    #38711670
WitC
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
Привет!
есть некий класс в котором есть статическое событие к которому подписан экземплярный метод...
не суть важно, конструкция работает...

так как событие статическое, ссылки на экземплярные классы (через подписанный метод) "живут" до закрытия ВСЕГО приложения,
из-за чего сборщик мусора не может удалить не нужные экземпляры (которые уже использованы и сброшены)...

прочитал статью и пример про слабые ссылки:
http://sonyks2007.blogspot.com/2013/11/c_6109.html
"выдрал" кусок кода:
Код: 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.
public sealed class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
{
    private readonly WeakReference _targetReference;
    private readonly MethodInfo _method;

    public WeakEventHandler(EventHandler<TEventArgs> callback)
    {
        _method = callback.Method;
        _targetReference = new WeakReference(callback.Target, true);
    }

    public void Handler(object sender, TEventArgs e)
    {
        var target = _targetReference.Target;
        if (target != null)
        {
            var callback = (Action<object, TEventArgs>)Delegate.CreateDelegate(typeof(Action<object, TEventArgs>), target, _method, true);
            if (callback != null)
            {
                callback(sender, e);
            }
        }
    }
}


и всё заработало, память не перегружается...
теперь, для некоторых классов, требуется как-то отписаться от события...
и, что-то у меня не получилось...
есть какие-нибудь идеи???

Спасибо.
...
Рейтинг: 0 / 0
03.08.2014, 19:17
    #38711683
Алексей К
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
...
Рейтинг: 0 / 0
04.08.2014, 21:52
    #38712590
WitC
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
Алексей К,
да, всё получилось, спасибо.
шаблон с WeakEventManager не реализовывал.
но изучение данной ссылки, показало на организацию буфера...
что я и сделал с WeakReference.

всем спасибо.
...
Рейтинг: 0 / 0
05.08.2014, 21:15
    #38713462
Ростигай
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
Объясните как работают слабые ссылки пожалуйста.
Если мы делаем слабую ссылку на объект, то после этого его может удалить сборщик мусора в любой момент.

Код: c#
1.
2.
3.
WeakReference<object> myWeakObj = GetSomeCashedObject ();
GC.Collect();
object myObj = myWeakObj.Target; // myObj всегда будет null ?



Сборщик мусора чистит поколение 0 очень часто и сам. GC.Collect лишь показывает идею. В худшем случае, может так выйти, что сборщик мусора будет вызван сразу, как только мы создали слабую ссылку, и объект тут же улетит ?
Выходит так, что объект по слабой ссылке чаще всего проживет всего лишь секунды ( если только сборщик мусора не перевел его в поколение 1, пока объект еще висел на сильной ссылке, перед передачей в слабую ссылку. Но и там он не будет жить вечно). В чем тогда смысл слабых ссылок, если почти наверняка при обращении к объекту, его уже не будет ?
...
Рейтинг: 0 / 0
05.08.2014, 21:55
    #38713474
gandjustas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
Ростигай,

Слабы ссылки нужны для двух вещей:
1) Подписка на события. Ибо если объект A подписывается на событие объекта Б, то Б начинает хранить неявную ссылку на А. Получается что долгоживущий объект Б может продлевать время жизни маленьких объектов.
2) Реализация вещей, вроде AttachedProperties в WPF, когда надо из статического класса ссылаться на относительно короткоживущие визуальные компоненты.

В общем когда надо ссылаться из долгоживущего на короткоживущие объекты могут пригодиться слабые ссылки.
...
Рейтинг: 0 / 0
06.08.2014, 21:27
    #38714545
WitC
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Слабые ссылки WeakReference
Ростигай,
всё верно, в предыдущем топике...
...
Относительно моих потребностей, нужно было привязать к неким объектам, некоторые свойства,
при этом не расширяя сами объекты. Для реализации я создал буфер, где ключ - расширяемый объект,
а значение - класс с расширенными свойствами, методами, логикой...
Кол-во объектов ~1,5 млн. Теперь представь, по какому-то событию требуется проверить расширенные свойства объекта и,
если условия выполняются, выполнить какую-то логику.
Какие варианты?
я нашёл два:
1. цикл
2. сделать в классе-расширителе статический метод, дёргать его (по названию класса!), и из него уже вызывать нужный метод (экземплярный!), где в свою очередь проверять конкретные (экземплярные!) значения, и выполнять логику.
Т.к. в статических методах мы не можем вызывать или обрабатывать экземплярные объекты,
пришлось сделать статическое событие к которому я привязал экземплярный метод.
Таким образом, схема работает так:
1. Где-то, по какому-то событию, я дергаю статический метод класса-расширителя.
2. Статический метод дёргает статическое событие, а событие в свою очередь, вызывает экземплярный метод!!!!
При чём событие отрабатывает у всех инициализированных объектов (цикла не надо!).
В принципе всё. Мне не приходится под каждую обработку логики делать циклы, где проверять условия и запускать логику,
теперь мне достаточно вызвать один статический метод, а запущенное статическое событие дёрнет экзеплярный метод
с его конкретными (для данного экземпляра) переменными, которые и проверит...
А дальше моя проблема.
Так как классов расширителей довольно много, то памяти они отжирают не мерянно. Примерно так,
предположим, один экземпляр класса-расширителя весит 500 байт, таким образом 1 млн экземпляров отожрут
500 000 000 /1000/1000 ~500Мб... ну с таким массивом справится современный комп... хотя жаба давит)))...
Естевственно, хочется экономить. Многие объекты, которые расширяются, имеют расширенные настройки по-умолчанию,
т.е. пользователь не сможет обработать такой массив, поэтому в буфере создаются только те классы-расширители,
в которых настройки индивидуальны, всем остальным подставляем один и тот же класс с настройками по-умолчанию.
Если пользователь меняет настройку - записываем его в буфер, в соответствии с объектом-хозяином...
Если пользователь ставит значения по умолчанию - то мы удаляем его из буфера, и объект пользуется общим классом-расширителем...
Вот тут и случилось.
Класс-расширитель я удалил, а память - забита, при создании следующей партии расширителей - память удваивается в размерах... и не скидывается! Я ожидал, типа класс-расширитель удалён из буфера, ссылки на него больше ни где нет,
сборщик муссора собирёт. При принудительном вызове GC (специально сделал деструктор с точкой остановки),
деструктор не отработал , т.е. объект живёт. При создании следующих классов-расширителей - они также не выгружаются...
Деструктор срабатывает только по закрытии всего приложения (тут точно ссылок не осталось))))... Так я и вспомнил про статическое событие, с привязкой на экзеплярыный метод, т.е. фактически с сылкой на экземляр!... Пока живёт статический объект с моей ссылкой, выгрузить экземпляр не реально!
Итог:
1. статическое событие вяжем слабой ссылкой с экземпляром.
2. сильная ссылка на созданный экземпляр хранится в буфере, с такой ссылкой сборщик муссора объект не удалит!
3. как только объект нам не нужен - мы удаляем сильную ссылку из буфера, а с оставшейся слабой ссылкой,
класс-расширитель будет успешно собран при последующей работе сборщика муссора.

Следите за утечками.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Слабые ссылки WeakReference / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]