Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Может ли использование лямбд в качестве обработчиков событий вызвать утечку памяти?
Скажем, у нас есть следующий метод:
private MyObject foo = new MyObject();
// and later in the class
public void PotentialMemoryLeaker(){
int firedCount = 0;
foo.AnEvent += (o,e) => { firedCount++;Console.Write(firedCount);};
foo.MethodThatFiresAnEvent();
}
Если класс с этим методом создается экземпляр и метод PotentialMemoryLeaker вызывается несколько раз, происходит ли утечка памяти?
Есть ли какой-нибудь способ отцепить этот обработчик событий lambda после того, как мы закончим вызывать MethodThatFiresAnEvent ?
Да, сохраните его в переменную и отцепите ее.
DelegateType evt = (o, e) => { firedCount++; Console.Write(firedCount); };
foo.AnEvent += evt;
foo.MethodThatFiresAnEvent();
foo.AnEvent -= evt;
И да, если вы этого не сделаете, вы будете пропускать память, так как каждый раз будете подключать новый объект делегата. Вы также заметите это, потому что каждый раз, когда вы вызываете этот метод, он будет сбрасывать в консоль все большее количество строк (не просто увеличивающееся число, но для одного вызова MethodThatFiresAnEvent он будет сбрасывать любое количество элементов, по одному разу для каждого подключенного анонимного метода).
Ваш пример просто компилируется в закрытый внутренний класс с именем компилятора (С полем firedCount и именованным компилятором методом). Каждый вызов функции PotentialMemoryLeaker создает новый экземпляр класса closure, на который where foo сохраняет ссылку посредством делегата на единственный метод.
Если вы не ссылаетесь на весь объект, который владеет PotentialMemoryLeaker, то все это будет собираться мусор. В противном случае вы можете либо установить foo в null, либо опустошить список обработчиков событий foo, написав это:
foreach (var handler in AnEvent.GetInvocationList()) AnEvent -= handler;
Конечно, вам понадобится доступ к закрытым членам класса MyObject.
Да, точно так же, как обычные обработчики событий могут вызывать утечки. Потому что lambda фактически изменено на:
someobject.SomeEvent += () => ...;
someobject.SomeEvent += delegate () {
...
};
// unhook
Action del = () => ...;
someobject.SomeEvent += del;
someobject.SomeEvent -= del;
Так что в основном это просто короткая рука для того, что мы использовали в 2.0 все эти годы.