memory-leaks - утечка - утечки памяти в node js




Может ли использование lambdas в качестве обработчиков событий вызвать утечку памяти? (4)

Скажем, мы имеем следующий метод:

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 ?


Ваш пример просто компилируется в закрытый внутренний класс с именем-компилятором (с полем firedCount и методом с использованием компилятора). Каждый вызов PotentialMemoryLeaker создает новый экземпляр класса замыкания, в котором где foo хранит ссылку посредством делегата для одного метода.

Если вы не ссылаетесь на весь объект, которому принадлежит PotentialMemoryLeaker, то все это будет собирать мусор. В противном случае вы можете установить foo в нулевой или пустой список обработчиков событий foo, написав это:

foreach (var handler in AnEvent.GetInvocationList()) AnEvent -= handler;

Конечно, вам нужен доступ к частным членам класса MyObject .


Вы не просто утечка памяти, вы также получите свою лямбду несколько раз. Каждый вызов «PotentialMemoryLeaker» добавит еще одну копию лямбда в список событий, и каждая копия будет вызываться при запуске «AnEvent».


Да, сохраните его в переменной и отцепите.

DelegateType evt = (o, e) => { firedCount++; Console.Write(firedCount); };
foo.AnEvent += evt;
foo.MethodThatFiresAnEvent();
foo.AnEvent -= evt;

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


Ну, вы можете расширить то, что было сделано здесь, чтобы сделать делегатов более безопасными (без утечек памяти)





event-handling